【2022-09-14】米哈游秋招笔试三道编程题

恭喜发现宝藏!搜索公众号【TechGuide】回复公司名,解锁更多新鲜好文和互联网大厂的笔经面经,目前已更新至美团、微软…
作者@TechGuide【全网同名】
点赞再看,养成习惯,您动动手指对原创作者意义非凡?

第一题:最短子串

题目描述

米小游拿到了一个字符串,她想截取一个连续子串,使得该子串中包含至少k个连续的“mihoyo”。

你可以帮米小游求出最短的子串长度,以及对应的子串位置吗?

输入描述

第一行输入两个正整数n和k,用空格隔开。

第二行输入一个长度为n的、仅由小写字母组成的字符串。1≤k≤n≤200000

22 2

mihoyoyomihoyomimihoyo

输出描述

如果不存在这样一个连续子串,请输出-1。

否则输出两个正整数l,r,代表选取的子串的左下标和右下标(整个字符串左下标为0,右下标为n-1)。

请务必保证选择的连续子串包含至少k个"mihoyo",且长度是最短的。有多解时输出任意即可。

0 13

代码

Java版本

    public static void main1(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int k = sc.nextInt();
        String s = sc.next();
        String tmp = "mihoyo";
        List<Integer> l = new ArrayList<>();
        // 先尝试获取 mihoyo 的位置,这里用list存储m的索引
        for(int i = 0; i < n - 5; i++){
            boolean ok = true;
            for(int j = 0; j < 6; j++){
                if(s.charAt(i+j) != tmp.charAt(j)){
                    ok = false;
                }
            }
            if(ok){
                l.add(i);
                i += 5;
            }
        }
        // 不够 k 个
        if(l.size() < k){
            System.out.println(-1);
            return;
        }
        // 判断比较
        int retIdx = 0;
        int len = l.get(k-1) - l.get(0);
        for(int i = k; i < l.size(); i++){
            int tmplen = l.get(i) - l.get(i-k+1);
            if(tmplen <= len){
                retIdx = i-k+1;
                len = tmplen;
            }
        }
        System.out.println(l.get(retIdx)+" "+(l.get(retIdx+k-1)+5));
    }
// vx公众号关注TechGuide 实时题库 闪电速递

Python版本

n, k = map(int, input().split())
s = input()
a = []
start = 0
t = 'mihoyo'
while True:
    i = s.find(t, start)
    if i == -1: break
    a.append(i)
    start = i + 1
ans = float('inf')
ansl, ansr = 0, 0

if len(a) >= k:
    for i in range(len(a) - k + 1):
        l = a[i]
        r = a[i + k - 1] + 5
        if r - l + 1 < ans:
            ans = r - l + 1
            ansl, ansr = l, r

if ans == float('inf'): print(-1)
else: print(ansl, ansr)
# vx公众号关注TechGuide 实时题库 闪电速递

CPP版本

#include <bits/stdc++.h>

using namespace std;
int n, k;
string s;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> k;
    cin >> s;
    int idx = s.find("mihoyo");
    int ans = 2 * n;
    vector<int> a;
    int pre = 0;
    while (idx != -1) {
        a.push_back(idx + pre);
        pre = pre + idx + 6;
        string tmp = s.substr(pre);
        idx = tmp.find("mihoyo");
    }
    if (a.size() < k) {
        cout << -1 << endl;
        return 0;
    }
    int l = 0, r = 0;
    int ll, rr;
    while (r < a.size()) {
        while (r < a.size() &;&; (r - l) < k - 1) {
            r++;
        }
        if (r == a.size()) break;
        int end = a[r] + 5;
        int begin = a[l];
        if (end - begin + 1 < ans) {
            ans = end - begin + 1;
            ll = begin, rr = end;
        }
        l++;
    }
    cout << ll << " " << rr << endl;
    return 0;
}
// vx公众号关注TechGuide 实时题库 闪电速递

第二题:猜数字

题目描述

米小游心中想了一个正整数,她邀请了n个人来猜这个数。每个人会猜一个数ai,然后米小游会告诉对方猜的结果:大于等于米小游想的数(≥)或者小于米小游想的数(<)。

猜谜结束后,米小游统计了共有x个≥和y个<。请你判断米小游初始想的数有多少种不同的可能?

输入描述:

输出描述:

input:

output:

输入描述

第一行输入一个正整数n,代表猜谜的人数。

第二行输入n个正整数ai,代表每个人猜的数字。

第三行输入两个整数x和y,用空格隔开。

1≤x+y=n≤1e5,1 ≤ ai ≤ 1e9

3
1 5 3
0 3

输出描述

如果有无穷多种可能,输出"infinity"

否则输出一个整数,代表米小游心中想的数的不同可能数量。

infinity

代码

Java版本

    public static void main2(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int arr[] = new int[n];
        for(int i = 0; i < n; i++) arr[i] = sc.nextInt();
        int a = sc.nextInt(), b = sc.nextInt();
        Arrays.sort(arr);
        if(b == 0){ // 全部是小于等于的
            System.out.println(arr[0]);
            return;
        }
        if(a == 0) { // 全部是大于的
            System.out.println("infinity");
            return;
        }
        int left = arr[b-1], right = arr[b];
        if(left == right){ // left < x <= right 不成立
            System.out.println(-1);
            return;
        }else{
            System.out.println(right-left);
        }

    }
// vx公众号关注TechGuide 实时题库 闪电速递

Python版本

n = int(input())
*a, = map(int, input().split())
x, y = map(int, input().split())
a.sort()

if x == 0:
    print('infinity')
else:
    if y:
        l = a[y - 1]
    else:
        l = 1
    r = a[y]
    print(r - l)
# vx公众号关注TechGuide 实时题库 闪电速递

第三题:树的连通块

题目描述

米小游有一棵有根树,树上共有n个节点。

米小游指定了一个节点x为根,然后定义所有相邻的、编号奇偶性相同的节点为一个连通块。

米小游想知道,所有子树(共有n个子树)的连通块数量之和是多少?

举个例子:
在这里插入图片描述
如上图,3号节点被指定为根

然后3-1-5作为一个连通块,4号节点和2号节点为单独的连通块。

那么1号节点到5号节点,每个节点的子树连通块数量分别为:2、1、3、1、1,总连通块数量是8。

输入描述

5 3
1 2
1 3
3 4
5 1

输出描述

8

代码

Java版本

    static Map<Integer, Integer> map;
    static long ret;
    static List<List<Integer>> l;
    static boolean vis[];
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int root = sc.nextInt();

        vis = new boolean[n+1];
        map = new HashMap<>();
        ret = 0;

        l = new ArrayList<>();
        for(int i = 0; i <= n; i++){
            l.add(new ArrayList<>());
        }
        for(int i = 0; i < n-1; i++){
            int a = sc.nextInt();
            int b = sc.nextInt();
            l.get(a).add(b);
            l.get(b).add(a);
        }

        dfs(root);
        System.out.println(ret);
    }

    public static int dfs(int pos) {
        List<Integer> childs = l.get(pos);
        vis[pos] = true;
        // 当前节点是一个连通分量
        int tmp = 1;
        for(int child: childs){
            if(!vis[child]){
                // 获取 child 的连通分量
                tmp += dfs(child);
                // 如果同奇偶,则连通分量个数-1
                if(child % 2 == pos%2) {
                    tmp -=1;
                }
            }
        }
        ret += tmp;
        return tmp;
    }

// vx公众号关注TechGuide 实时题库 闪电速递

Python版本

import sys

sys.setrecursionlimit(int(2e5))

n, x = map(int, input().split())
g = [[] for _ in range(n + 1)]
for _ in range(n - 1):
    u, v = map(int, input().split())
    g[u].append(v)
    g[v].append(u)


def solve():
    ret = 0

    def dfs(cnt, pre):
        ans = 1
        for nxt in g[cnt]:
            if nxt == pre: continue
            ans += dfs(nxt, cnt)
            if (cnt & 1) == (nxt & 1): ans -= 1
        nonlocal ret
        ret += ans
        return ans

    dfs(x, -1)
    return ret
    
print(solve())
# vx公众号关注TechGuide 实时题库 闪电速递