美团8.6笔试Java版题解

> 1.给定a、b两种点心的数量,每个礼盒放3个点心,a、b至少各有一个,求最多能包多少个礼盒

public class Test01 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int num = sc.nextInt();
        for(int i=0;i<num;i++){
            int a = sc.nextInt();
            int b = sc.nextInt();
            int min = Math.min(a,b);
            int max = Math.max(a,b);
            if(max>=min*2){   //如果max>=2*min 由于每一份都至少需要一个min 所以答案就是min种(一个min,两个max)
                System.out.println(min);
            }
            else{       //如果  min<=max<2*min 那么此时肯定凑不够 一个min配2个max
                // 此时需要有min填补max的位置 答案从min开始减小 每次减小有两重效果
                // 例如 44 85  min=44 max=85  min = 44 max =44+41 不够
                // 当min取43时 min减少1 同时有多余的一个min和一个max可以补充 所以min-1的效果相当于补充了3个max
                //min=43 max = 43+42+1
                //本方***TLE 因此需要优化
                //将此处的两种情况总结 可以发现答案要么是min 要么是 a+b//3
                for(int k=min;k>=0;k--){
                    if(k<=(min-k)+(max-k)){
                        System.out.println(k);
                        break;
                    }
                }
            }
        }
    }
}
//所以可以写成
public class Test01 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int num = sc.nextInt();
        for(int i=0;i<num;i++){
            int a = sc.nextInt();
            int b = sc.nextInt();
            int min = Math.min(a,b);
            System.out.println(Math.min(min,(a+b)/3));
        }
}
}

2.给定一组0,-1,+1数组,分割点k左大于等于0、右侧小于等于0的为异常数据,求最乐观情况下有多少个异常数据

public class Test02 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int num = sc.nextInt();
        int[] nums = new int[num];
        for(int i=0;i<num;i++){
            nums[i]=sc.nextInt();
        }
        int[] min = new int[num+2]; //记录左侧有多少个>=0的数
        int[] max = new int[num+2]; //记录右侧有多少个<=0的数

        for(int i=0;i<num;i++){
            if(nums[i]<0){
                min[i+1]=min[i];
            }else {
                min[i+1]=min[i]+1;
            }
        }
        for(int i=num-1;i>=0;i--){
            if(nums[i]<=0){
                max[i+1]=max[i+2]+1;
            }else {
                max[i+1]=max[i+2];
            }
        }
        min[min.length-1]=min[min.length-2]; //处理边界条件
        max[0]=max[1];                        //处理边界
        int res = Integer.MAX_VALUE;
        for(int i=0;i<num+1;i++){
            res = Math.min(res,min[i]+max[i+1]);
        }

        System.out.println(res);
        //Arrays.stream(min).forEach(System.out::print);
        //System.out.println();
        //Arrays.stream(max).forEach(System.out::print);
    }
}

3.给定一组魔法石正面和反面表示的数字,只有当至少一半相同数字的面朝上可以触发法阵,初始状态为全部朝上,求最少需要翻转多少块石头可以触发法阵,无解输出-1

public class Test03 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int nums = Integer.parseInt(sc.nextLine());
        int[] front = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
        int[] back = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
        Map<Integer,Integer> frontNum = new HashMap<>();//记录正面的个数 key 种类 value 个数
        Map<Integer,Integer> AllNum = new HashMap<>(); //记录全部的无重复的个数 key种类 value 正反不重复个数
        for(int num:front){
            frontNum.put(num,frontNum.getOrDefault(num,0)+1);
        }
        AllNum.putAll(frontNum);//frontnum 的map进行 深拷贝
        for(int i=0;i<back.length;i++){
            if(back[i]!=front[i]) AllNum.put(back[i],AllNum.getOrDefault(back[i],0)+1);
        }
        int target = (nums+1)/2;
        int res =Integer.MAX_VALUE;
        for(int i:AllNum.keySet()){
            if(AllNum.getOrDefault(i,0)>=target)//如果总数不足target 直接排除掉
                if(frontNum.getOrDefault(i,0)>=target){ //如果正面已经超过了target 不需要再做改变
                    res = 0;
                    break;
                }else {//否则就需要翻转target-正面朝上的数目
                    res = Math.min(res,target-frontNum.getOrDefault(i,0));
                }
        }
        res= res == Integer.MAX_VALUE?-1:res;
        System.out.println(res);

    }
}

4.给定n个样本的类别编号,输入的次序为样本编号,每类样本编号最小的(m+1)/2为训练集,剩下的为测试集。按照样本编号升序输出所有训练集样本及训练集样本

public class Test04 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int k = sc.nextInt();
        int[] nums = new int[n];
        for(int i=0;i<n;i++){
            nums[i]=sc.nextInt();
        }
        int[] count = new int[k+1];
        for(int i=0;i<n;i++){
            count[nums[i]]++;
        }

        for(int i=0;i<=k;i++){
            if(count[i]%2==1){
                count[i]=(count[i]/2+1);
            }else
                count[i]=(count[i]/2);
        }
        List<Integer> res = new ArrayList<>();
        List<Integer> tr = new ArrayList<>();
        for(int i=0;i<n;i++){
            if(count[nums[i]]>0){
                res.add(i+1);
                count[nums[i]]--;
            }else {
                tr.add(i+1);
            }
        }
        for (int i=0;i<res.size();i++){
            System.out.print(res.get(i));
            if(i!=res.size()-1)
            System.out.print(" ");
        }
        System.out.println();
        for (int i=0;i<tr.size();i++){
            System.out.print(tr.get(i));
            if(i!=tr.size()-1)
                System.out.print(" ");
        }
    }
}

5.将字符串s丢入机器后则输出新字符串s+reverse(s)+"wow"。初始字符串为"MeiTuan",不停的反复将新字符串丢入机器,求得到的无限长字符串的第k位字母(1 ≤ k ≤ 1e18)

public class Test05 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int i = sc.nextInt();
        System.out.println("MeiTuannauTieMWoWWoW".charAt((i-1)%20)); //发现一直是这20个字符在循环
    }
}

侵删

#美团笔试#
全部评论
最后那个i要减1的,计数是从0开始的
点赞 回复 分享
发布于 2022-08-06 18:04

相关推荐

评论
7
35
分享
牛客网
牛客企业服务