20220806 美团笔试五道编程题(附AK题解)

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

第一题:礼品盒分配

题目:

小美做饼干,有AB两种,做成礼盒卖,每个礼盒三个饼干,且至少包含一个A 和 一个B。现在给你A和B的数量,问最多可以做多少礼盒?

思路:

分析了一下,礼盒的数量为(A,B,(A+B)/3)三者的最小值。

代码

CPP版本
int main() {
    int T;
    cin >> T;
    int x;
    int y;
    while (T--) {
        cin >> x >> y;
        int ans = min({(x+y)/3, x ,y});
        cout << ans << endl;
    }
    return 0;
}
// 微信公众号关注TechGuide 实时题库 闪电速递
Java版本
import java.util.Scanner;

public class Q1 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        for (int i = 0; i < N; i++) {
            int x = sc.nextInt();
            int y = sc.nextInt();
            System.out.println(getCount(x,y));
        }
    }

    public static int getCount(int A,int B){
        //假设能做x盒,那么 x<=A x<=B 且 3x<=A+B
        int x = (A+B)/3;
        x = Math.min(x,A);
        x = Math.min(x,B);
        return x;
    }
}
// 微信公众号关注TechGuide 实时题库 闪电速递

第二题:实验结果

题目:

小美做实验,有一个纸带上有若干个数字,在纸带上选择一个位置k,k是分割点(比如k选3,那么左边是123,右边是456),k左边大于等于0的点为异常点,k右边小于等于0的点为异常点。

现在给一个纸带,不给k,问你最乐观情况下异常点最少个数为多少(选哪个k异常点最少吧)

思路:

用前缀数组,记录每个点左边的异常点,再从右边计算异常点回来,每次左右异常点个数相加,取最小一个。

题解

CPP版本
int main() {
    int N;
    cin  >> N;
    vector<int> nums;
    int sum = 0;
    int num;
    int mis = 0;
    for (int i=0; i<N; ++i) {
        cin >> num;
        if (num == 0) {
            ++mis;
        }
        else {
            nums.push_back(num);
            sum += num;
        }
    }
	// 微信公众号关注TechGuide 实时题库 闪电速递

    int mis1 = INT_MAX;
    int preSum = 0;
    int n = nums.size();
    for (int i=0; i<n; ++i) {
        int p1 = (i + preSum) / 2;
        int p2 = ((n-i) - (sum - preSum)) / 2;
        preSum += nums[i];
        mis1 = min(mis1,p1+p2);
    }
    mis1 = min(mis1, (n-preSum)/2);
    cout << mis1+mis<<endl;
}
Java版本
import java.util.Scanner;

public class Q2 {
    public static void main(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();
        }
        System.out.println(minException(arr));
    }
	// 微信公众号关注TechGuide 实时题库 闪电速递

    public static int minException(int arr[]){
        int n = arr.length;
        int ans = Integer.MAX_VALUE;
        int leftException[] = new int[n];
        leftException[0] = 0;
        for(int i = 1; i < n; i++){
            leftException[i] = leftException[i-1];
            if(arr[i-1]>=0){
                leftException[i]++;
            }
        }
      //  printArr("leftException",leftException);
        int rightException = 0;
        for(int i = n-1; i>=0; i--){
            if(arr[i]<=0) rightException++;
            ans = Math.min(ans,leftException[i]+rightException);
        }
        return ans;
    }

    public static void printArr(String str ,int arr[]){
        System.out.println(str);
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+"\t");
        }
        System.out.println();
    }
}

第三题:翻转石头

题目

小美有n个魔法石,每个魔法石有正反两个数字,一开始全部正面朝上,魔法石要激活需要有一半以上的魔法石数字相同,问你把魔法石激活的最小翻牌次数(把魔法石从正面变反面)

每个魔法石有两面,分为正面和反面,正面有一个数字,反面有一个数字。然后一开始魔法石全部正面朝上。魔法石要激活,要魔法石中有相同数字的魔法石数量超过一半才可以。然后你可以对魔法石进行翻面,问最少翻多少次能激活魔法石。

思路

计每个牌出现的数量,因为能出现一半以上的最多四种吧,然后去遍历能出现一半以上的数量,然后去扣掉正面牌上这个数的数量,就是需要翻牌的数量。然后找最小

代码

CPP版本
#include <iostream>
#include <algorithm>
#include <vector>
#include <limits.h>
#include <unordered_map>
using namespace std;
// 翻石头
int main() {
    int N;
    cin >> N;
    vector<long long> nums1(N);
    vector<long long> nums2(N);
    unordered_map<long long, int> map1;
    unordered_map<long long, int> map0;
    long long num;
    for (int i=0; i<N; ++i) {
        cin >> num;
        map1[num]++;
        nums1[i] = num;
    }
    map0 = map1;
    for (int i=0; i<N; ++i) {
        cin >> num;
        nums2[i] = num;
        if (nums1[i] != num) {
            map0[num]++;
        }
    }
    int ret = INT_MAX;
    int target = (N+1)>>1;
    for (auto& item : map0) {
        if (item.second < target) continue;
        int have = map1[item.first];
        if (have >= target) {
            ret = 0;
            break;
        }
        else {
            ret = min(ret, target-have);
        }
    }
    ret = ret==INT_MAX? -1 : ret;
    cout << ret << endl;
    return 0;
}  
// 微信公众号关注TechGuide 实时题库 闪电速递
Java版本
import java.util.HashMap;
import java.util.HashSet;
import java.util.Scanner;

public class Q3 {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int up[] = new int[n];
        int down[] = new int[n];
        for (int i = 0; i < n; i++) {
            up[i] = sc.nextInt();
        }
        for (int i = 0; i < n; i++) {
            down[i] = sc.nextInt();
        }
        System.out.println(minOps(n,up,down));
    }
	// 微信公众号关注TechGuide 实时题库 闪电速递

    public static int minOps(int n, int[] up, int[] down){
        HashMap<Integer,Integer> allMap = new HashMap<>();
        HashMap<Integer,Integer> upMap = new HashMap<>();
        //先统计个数
        for (int i = 0; i < n; i++) {
            //两面相同统计一次
            allMap.put(up[i],allMap.getOrDefault(up[i],0)+1);
            if(up[i]!=down[i]){
                allMap.put(down[i],allMap.getOrDefault(down[i],0)+1);
            }
            upMap.put(up[i],upMap.getOrDefault(up[i],0)+1);
        }

        int target = n%2==0?n/2:n/2+1;
        int ans = n+1;
        for (Integer key : allMap.keySet()) {
            if(allMap.get(key)>=target){
                ans = Math.min(ans,upMap.getOrDefault(key,0)>=target?0:target-upMap.getOrDefault(key,0));
            }
        }
        return ans==n+1?-1:ans;
    }
}

第四题:分割训练集和测试集

题目:

按顺序给你一堆训练集(只有类别编号),就是给了一个数组,然后每个类别中,前(类别数据个数)/2向上取整为训练集,后面的是测试集,让我们按顺序拆分

思路:

计数拆分

代码

CPP版本
#include <iostream>
#include <algorithm>
#include <vector>
#include <limits.h>
#include <unordered_map>
using namespace std;
// 分割训练集 和 测试集
ostream& operator<<(ostream& os, vector<int>& nums) {
    for (int num : nums) {
        os << num << " ";
    }
    os << endl;
    return os;
}
int main() {
    int N;
    int m;
    cin >> N >> m;
    unordered_map<int,int> map;
    vector<int> nums(N);
    vector<int> train;
    vector<int> test;
    int num;
    for (int i=0; i<N; ++i) {
        cin >> num;
        map[num]++;
        nums[i] = num;
    } 
    for (auto& item : map) {
        item.second = (item.second+1) / 2;
    }
    for (int i=0; i<N; ++i) {
        if (map[nums[i]] > 0) {
            train.push_back(i+1);
            map[nums[i]]--;
        }
        else {
            test.push_back(i+1);
        }
    }
    cout << train << test;
    return 0;
} 
// 微信公众号关注TechGuide 实时题库 闪电速递
Java版本
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Q4 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int k = sc.nextInt();
        int cnt[] = new int[k+1];
        int arr[] = new int[n];
        for (int i = 0; i < n; i++) {
            arr[i] = sc.nextInt();
            cnt[arr[i]]++;
        }
        int order[] = new int[k+1];//表示k当前访问的个数
        List<Integer> train = new ArrayList<>();
        List<Integer> test = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            order[arr[i]]++;
            if(order[arr[i]] <= (cnt[arr[i]]%2==0?cnt[arr[i]]/2:cnt[arr[i]]/2+1)){
                train.add(i+1);
            }
            else{
                test.add(i+1);
            }
        }
        for (int i = 0; i < train.size()-1; i++) {
            System.out.print(train.get(i)+" ");
        }
        if(train.size()>0)
            System.out.println(train.get(train.size()-1));
        else{
            System.out.println();
        }
        for (int i = 0; i < test.size()-1; i++) {
            System.out.print(test.get(i)+" ");
        }
        if(test.size()>0) System.out.println(test.get(test.size()-1));
        else System.out.println();
    }
}
// 微信公众号关注TechGuide 实时题库 闪电速递

第五题:第K个数字

题目:

初始字符串为MetTuan,每次对字符串做 str = str + str.reverse() + "wow"的操作,无限循环。后面给你一个k,问你位置k的字符为什么。

思路

找规律
无限循环后 是 str+str.reverse()+"wowwow"的无限循环

代码

CPP版本
#include <iostream>
#include <algorithm>
#include <vector>
#include <limits.h>
#include <unordered_map>
#include "string" 
using namespace std;
//f(s) = s + r(s) + "wow";
string orgin = "MeiTuannauTieMwow";
char getNth(long long k, vector<long long>& cnt) {
    if (k <= 7) return orgin[k-1];
    int i = cnt.size()-1;
    for ( ; i>=0; --i) {
        if (k > cnt[i]) break;
    }
    k -= cnt[i];
    if (k <= cnt[i]) {
        long long idx = cnt[i] - k + 1;
        return getNth(idx, cnt);    
    }
    else {
        k -= cnt[i];
        if (k == 1) return 'w';
        if (k == 2) return 'o';
        if (k == 3) return 'w';
    }
    
} 
int main() {
    vector<long long> cnt(55);
    cnt[0] = 7;
    for (int i=1; i<cnt.size(); ++i) {
        cnt[i] = cnt[i-1]*2 + 3;
    }
    int N;
    cin >> N;
    long long k;
    while (N--) {
        cin >> k;
        char c = getNth(k,cnt);
        cout << c << endl;
    }
    return 0;
}
// 微信公众号关注TechGuide 实时题库 闪电速递
Java版本
import java.util.Scanner;

public class Q5 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int T = sc.nextInt();
        String str = "MeiTuan";
        str = str + (new StringBuilder(str).reverse().toString())+"wowwow";
        for (int i = 0; i < T; i++) {
            long pos = sc.nextLong()-1;
            pos = pos % str.length();
            System.out.println(str.charAt((int)pos));
       }
    }
	// 微信公众号关注TechGuide 实时题库 闪电速递

    public static String function(String str){
        return str + (new StringBuilder(str).reverse().toString()) + "wow";
    }
    /*
    s
    s fs wow
    (s fs wow) (wow s fs) wow
    [(s fs wow) (wow s fs) wow][wow (s fs) wow wow (s fs)] wow
    {[(s fs wow) (wow s fs) wow][wow (s fs) wow wow (s fs)] wow} {wow s fs wow wow s fs wow wow s fs wow wow sfs w
     */
}
  • 1
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值