Seeker的奇妙求职历险(华为笔试)

矩阵报数

题目:
给出一个旋转矩阵,M行N列,左上角为(0,0),右下角为(M-1,N-1),从左上角开始计数,顺时针从外圈开始,外圈遍历完之后再遍历内圈,直到遍历完所有的点。
返回所有个位数为7且十位数为奇数的坐标,10 <= M,N <= 1000,当输入不合法的时候返回空数组。

输入 M,N
10 10
输出
[[7,9],[1,1],[8,2],[7,5],[4,4]]

分析:题目不难理解,剑指offer上面题目的变种,判断一下是否合法,合法就加入结果集。
但是我一直卡在70%,一开始以为是超时,后来做完看牛客才知道原来题目中说的10 <= M,N <= 1000不是输入数据的大小而是如果数据超过这个范围要返回空数组。
看来是题目做少了,没想明白门道,我还一直在想怎么会超时。

    public static void main(String[] args){
     
        Scanner scan = new Scanner(System.in);
        int m = scan.nextInt();
        int n = scan.nextInt();
        int left = 0;
        int right = n-1;
        int up = 0;
        int down = m-1;
        int index = 1;
        List<int[]> res = new ArrayList<>();
        //记得判断一下数据范围
        while(n >= 10 && m >= 10 && n<= 1000 && m <= 1000){
     
            for(int i=left;i<=right;i++){
     
                if(check(index))
                    res.add(new int[]{
     up,i});
                index++;
            }
            up++;
            if(up > down)
                break;
            for(int i=up;i<=down;i++){
     
                if(check(index))
                    res.add(new int[]{
     i,right});
                index++;
            }
            right--;
            if(left > right)
                break;
            for(int i=right;i>=left;i--){
     
                if(check(index))
                    res.add(new int[]{
     down,i});
                index++;
            }
            down--;
            if(up > down)
                break;
            for(int i=down;i>=up;i--){
     
                if(check(index))
                    res.add(new int[]{
     i,left});
                index++;
            }
            left++;
            if(left > right)
                break;
        }
        System.out.print('[');
        for(int i=0;i<res.size();i++){
     
            int[] tmp = res.get(i);
            System.out.print('[');
            System.out.print(tmp[0]);
            System.out.print(',');
            System.out.print(tmp[1]);
            System.out.print(']');
            if(i!=res.size()-1)
                System.out.print(',');
        }
        System.out.print(']');
    }
    public static boolean check(int index){
     
        if((index%10 == 7) && (((index/10)&1) == 1))
            return true;
        return false;
    }

二叉树的个数

题目:给出一个数组,数组中的元素代表二叉树中一个节点的深度,求这个数组能够组成多少种二叉树。结果可能很大,需要mod(10^9+7)

输入 第一行为一个数组,代表元素个数,第二行为一组数据
4
0 1 2 2

分析:这道题的思路是先判断当前层有最多有多少个节点,然后看一下数组中当前层的节点个数,根据排列组合公式累乘。
解法不难,一直卡在50%,以为是溢出的问题,把所有数据改成long,还是50%,后来看牛客才知道原来输入数据可能构不成一颗二叉树,这个时候要返回0,比如有一层节点个数为0,有一层节点个数超出了上限。
看来还是题做少了,华为就喜欢搞这种奇奇怪怪的输入输出。

public static void main(String[] args) {
     
    Scanner in = new Scanner(System.in);
    int n = in.nextInt();
    int[] nums = new int[n];
    for(int i=0;i<n;i++){
     
        nums[i] = in.nextInt();
    }
    System.out.println(getRest2(nums));
}

private static long getRest2(int[] nums) {
     
    long max = nums[0];
    HashMap<Integer,Integer> map = new HashMap<>();
    for(int now:nums){
     
        map.put(now,map.getOrDefault(now,0)+1);
        max = Math.max(max,now);
    }
    int pre = map.get(0);
    if(pre != 1)
    	return 0;
    long res = 1;
    for(int i=1;i<=max;i++){
     
        int now = map.get(i);
        //判断一下非法情况
        if(now == 0 || now > pre*2)
        	return 0;
        res = res*getNum(now,pre*2)%MOD;
        pre = now;
    }
    return res;
}

private static long getNum(int m, int n) {
     
    long num1 = 1;
    long num2 = 1;
    for(long i=n-m+1;i<=n;i++){
     
        num1=num1*i%MOD;
    }
    for (long i=1;i<=m;i++){
     
        num2 = num2*i%MOD;
    }
    return num1/num2;
}

俄罗斯方块

题目:
俄罗斯方块。给定字符串frame和brike,frame类似2202这种,表示长为4,高为2,2,0,2的方块(每个方块的单位为1,该位是2就是两个堆在一起),brike类似121,表示长为3,高为121的方块(多的那个向下)。如果一行被填充满了即可消除掉。问给定了两个字符串之后,最后剩下的最小行数是多少。
(题干来自于牛客作者zshunyi,原贴)

输入 第一行表示底部每一列的高度,第二行表示方块每一列的高度,都是向下凸的。
2202
2
输出 表示剩余的最小行数
0

分析:就模拟,听说测试用例比较弱。不过我只过了70%不知道哪里有问题。
这里贴一份大佬cuber~的代码,代码来源。

int helper(vector<int>& frame, vector<int>& brick)
{
     
    int frame_n = frame.size(), brick_n = brick.size();

    int res = 1000000;

    for (int i = 0;i < frame_n - brick_n + 1;i++)
    {
     
        int max_h = 0, total_max_h;
        for (int j = 0;j < brick_n;j++)
            max_h = max(max_h, brick[j] + frame[i + j]);
        total_max_h = max_h;
        int r = 100000;
        for (int j = 0;j < frame_n;j++)
        {
     
            total_max_h = max(total_max_h, frame[j]);
            if (j < i)
                r = min(r, frame[j]);
            else if (j >= (i + brick_n))
                r = min(r, frame[j]);
            else
            {
     
                int tmp1 = frame[j], tmp2 = brick[j - i];
                if (tmp1 + tmp2 == max_h)
                    r = min(r, max_h);
                else
                    r = min(r, tmp1);
            }
        }
        res = min(res, total_max_h - r);
    }
    return res;
}

int main()
{
     
    string s1, s2;
    cin >> s1 >> s2;
    vector<int> frame(s1.size()), brick(s2.size());
    for (int i = 0;i < s1.size();i++) frame[i] = s1[i] - '0';
    for (int i = 0;i < s2.size();i++) brick[i] = s2[i] - '0';

    cout << helper(frame, brick);

    return 0;
}

后记

上周华为的笔试感觉好像简单一些,可惜没能参加,那天晚上面的PCG还把我挂了,真难受。
昨天晚上5点的时候,腾讯发邮件叫我晚上8点面试,和华为笔试撞上了就调到了周五晚上。结果没想到过了一夜,先是美团发邮件说周六下午笔试,然后11点时候腾讯发邮件说周日晚上8点笔试,最后今天滴滴发邮件说周五晚上笔试。
关键是滴滴的第二批笔试都到9月中了,没办法,又联系hr改腾讯的面试时间。
淦,为什么你们都喜欢挤在一起啊,雷火这边约了明天早上面试,这次应该是hr面了吧,有道还是没消息。
秋招真难,希望晚上腾讯不要凉的太快。


Seeker的奇妙求职历险(华为笔试)_第1张图片

你可能感兴趣的:(Seeker的奇妙求职历险)