8月6日美团笔试题-后端AK代码

4 + 1 全部100%通过,但代码像shit一样,心情好时候再重构一下。

第一题,礼品盒分配

  • 解题思路:分情况进行讨论,礼盒数取决于 A B 最小值 和 A B 间的差值

    • 可以看做,先在每个礼盒中放入 一个 A 和 一个 B

    • max - min,就是在每个盒子中放入 1 A 和 1 B 后剩余的 sub

    • 如果 sub >= min,那么所有礼盒都可以满足 3 个礼品

    • 否则,不能将第一步中所有礼盒装满,直接返回 ( A + B) / 3即可

      public class Main {
      public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int T = input.nextInt();
        while (T-- > 0){
            int num1 = input.nextInt();
            int num2 = input.nextInt();
            System.out.println(getAns(num1, num2));
        }
      }
      public static int getAns(int x, int y){
        int min = Math.min(x, y), max = Math.max(x, y), sub = max - min;
        if(sub >= min) return min;
        else return (max + min) / 3;
      }
      }

      第二题 实验结果

      结题思路:

    • 采用 left 数组保存 i 之前的小于等于0的数量

    • 采用 right 数组保存 i 之后大于等于0的数量
      遍历即可

      public class Main {
      public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        while (input.hasNextLine()){
            int n = Integer.parseInt(input.nextLine());
            String[] line = input.nextLine().split(" ");
            int[] nums = new int[n];
            for(int i = 0; i < n; ++i) nums[i] = Integer.parseInt(line[i]);
      
            int[] left = new int[n], right = new int[n];
      
            int ans = n, count = 0;
            for(int i = 0; i < n; ++i){
                if(nums[i] >= 0) ++count;
                left[i] = count;
            }
            count = 0;
            for(int i = n - 1; i >= 0; --i){
                if(nums[i] <= 0) ++count;
                right[i] = count;
            }
            for(int i = 0; i <= n; ++i){
                int l = i == 0 ? 0 : left[i - 1];
                int r = i == n ? 0 : right[i];
                ans = Math.min(ans, l + r);
            }
            System.out.println(ans);
        }
      }
      }

第三题,魔法石

  • 首先根据第二行,进行预处理,对经过反转可以得到的数字进行统计
  • 再对第一行数据,进行排序,排序的作用就是计算相同数字的最大数量
  • 当 相同数字数量 + 反转数字可以得到的数量 >= (n + 1) / 2
  • 记录最小的翻转次数 (n + 1) / 2 - count
public class Main {

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        while (input.hasNextLine()){
            int n = Integer.parseInt(input.nextLine());
            int[][] arr = new int[n][2];

            String[] line = input.nextLine().split(" ");
            for(int i = 0; i < n; ++i) {
                arr[i][0] = Integer.parseInt(line[i]);
            }
            line = input.nextLine().split(" ");
            for(int i = 0; i < n; ++i) {
                arr[i][1] = Integer.parseInt(line[i]);
            }

            Arrays.sort(arr, (o1, o2) -> o1[0] - o2[0]);
            // map 记录由 第二行反转 每个数字 及由反转得到的最大数量
            Map<Integer, Integer> map = new HashMap<>();
            for(int i = 0; i < n; ++i){
                if(arr[i][1] != arr[i][0]) map.put(arr[i][1], map.getOrDefault(arr[i][1], 0) + 1);
            }

            int count = 1, ans = -1;

            for(int i = 1; i < n; ++i){
                if(arr[i][0] == arr[i - 1][0]){
                    ++count;
                    // 当 第一行数量 + 第二行反转数量 >= (n + 1) / 2,即满足要求
                    if(i == n - 1){
                        if(count + map.getOrDefault(arr[i][0], 0) >= (n + 1) / 2){
                            if(count >= (n + 1) / 2) ans = 0;
                            else{
                                if(ans == -1) ans = (n + 1) / 2 - count;
                                else ans = Math.min(ans, (n + 1) / 2 - count);
                            }
                        }
                    }
                }else{
                    // 当 第一行数量 + 第二行反转数量 >= (n + 1) / 2,即满足要求
                    if(count + map.getOrDefault(arr[i - 1][0], 0) >= (n + 1) / 2){
                        if(count >= (n + 1) / 2) ans = 0;
                        else{
                            if(ans == -1) ans = (n + 1) / 2 - count;
                            else ans = Math.min(ans, (n + 1) / 2 - count);
                        }
                    }
                    count = 1;
                }
            }

            if(ans == -1){
                for(int val : map.values()){
                    if(val >= (n + 1) / 2) ans = (n + 1) / 2;
                }
            }
            System.out.println(ans);
        }
    }
}

第四题 数学竞赛

public class Main {

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        while (input.hasNextLine()){
            String[] line = input.nextLine().split(" ");
            int n = Integer.parseInt(line[0]), k = Integer.parseInt(line[1]);
            int[] nums = new int[n];
            line = input.nextLine().split(" ");
            for(int i = 0; i < n; ++i) nums[i] = Integer.parseInt(line[i]);

            Map<Integer, List<Integer>> map = new HashMap<>();
            for(int i = 0; i < n; ++i){
                List<Integer> temp = map.getOrDefault(nums[i], new ArrayList<>());
                temp.add(i + 1);
                temp.sort((o1, o2) -> o1 - o2);
                map.put(nums[i], temp);
            }
            List<Integer> test = new ArrayList<>(), train = new ArrayList<>();
            for(int key : map.keySet()){
                List<Integer> arr = map.get(key);
                int size = arr.size();
                for(int i = 0; i < size; ++i){
                    if(i < (size + 1) / 2) train.add(arr.get(i));
                    else test.add(arr.get(i));
                }
            }
            test.sort((o1, o2) -> o1 - o2);
            train.sort((o1, o2) -> o1 - o2);

            for(int num : train) System.out.print(num + " ");
            System.out.println();
            for(int num : test) System.out.print(num + " ");
        }
    }

}

附加题 第K个数字

字符串的表示为 [source][rever][wow],三个部分
解题思路:使用字符串模拟,估计不是内存溢出,就是时间超时

  • 采用 index,和 len 去模拟字符串,根据 index 和 len 的关系,不断去缩小范围知道 index 在MeiTuannauTieMwow 这个字符串长度内

    • 如果 len - index < 3,那么刚坐标处于 "wow"结尾中

    • 如果 index > (len - 3) /2 ,那么index 处于 rever 这个范围中

    • 如果 index < (len - 3) / 2,那么index 处于 source这个返回中

    • 如果 index < "MeiTuannauTieMwow".length,那么直接返回

      public class Main {
      public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int n = Integer.parseInt(input.nextLine());
        while (n -- > 0){
            long target = Long.parseLong(input.nextLine());
      
            String str = "MeiTuannauTieMwow";
            long len = str.length();
      
            long index = target;
            while (index > len){
                len = len * 2 + 3;
            }
      
            while (true){
                if(len - index < 3) {
                    System.out.println("wow".charAt((int)(len - index)));
                    break;
                }else if(index <= str.length()){
                    System.out.println(str.charAt((int)(index - 1)));
                    break;
                }else if(index > (len - 3) / 2){
                    index = len - 3 - index + 1;
                    len = (len - 3) / 2;
                }else{
                    len = (len - 3) / 2;
                }
            }
        }
      }
      }
#美团笔试##美团招聘#
全部评论
第五题哪有那么🤣 public static void main(String[] args) {         Scanner sc = new Scanner(System.in);         String s1 = "MeiTuannauTieMwowwow";         long n = sc.nextLong();         for (long i = 0; i < n; i++) {             long k=sc.nextLong()-1;             k %= 20;             System.out.println(s1.charAt((int) k));         }     }
2 回复
分享
发布于 2022-08-06 15:28
牛的
1 回复
分享
发布于 2022-08-06 13:24
滴滴
校招火热招聘中
官网直投
第一题里面,为啥不满足的话直接两数相加除3就行呢,有点没理解
1 回复
分享
发布于 2022-08-06 14:09
魔法石那题,不是只能把原本是反面的摆为正面吗?怎么还有第二种情况呀
1 回复
分享
发布于 2022-08-06 14:22
第一题直接min(min(a,b),(a+b)/3))就行了
1 回复
分享
发布于 2022-08-06 17:51
大佬
点赞 回复
分享
发布于 2022-08-06 13:32
牛牛牛
点赞 回复
分享
发布于 2022-08-06 14:08
大佬,第一题里面( A + B) / 3  是什么思想?可以说一下吗。
点赞 回复
分享
发布于 2022-08-06 14:11
魔法石那题,这种情况[[1,1,2,2,2,4,5,6],[3,3,1,1,3,5,4,7]],魔法阵1在每一行都不是最多的,但最后选择的是魔法阵1
点赞 回复
分享
发布于 2022-08-06 14:40
点赞 回复
分享
发布于 2022-08-06 17:31
大佬,第二题中: left数组表示的是:i左边(包括i)大于等于0的数量 right数组表示的是:i右边(包括i)小于等于0的数量 是这样嘛?
点赞 回复
分享
发布于 2022-08-06 18:00
不是吧,这么难?没有力扣改编题吗😣
点赞 回复
分享
发布于 2022-08-07 10:14
第二题暴力法求解,是没考虑到什么内容吗?求教😫
点赞 回复
分享
发布于 2022-08-07 11:04
第五题的抽象美如画,感谢分享,学习了
点赞 回复
分享
发布于 2022-08-08 10:16
点赞 回复
分享
发布于 2022-08-08 11:23
这是提前批嘛
点赞 回复
分享
发布于 2022-08-08 12:54
美团内推找我哦,帮查进度😁,内推码ACfgTAb
点赞 回复
分享
发布于 2022-08-08 15:07
int l = i == 0 ? 0 : left[i - 1];这里为什么是i-1呀
点赞 回复
分享
发布于 2022-08-09 10:14

相关推荐

23 146 评论
分享
牛客网
牛客企业服务