zoukankan      html  css  js  c++  java
  • 【美团点评】2020校招算法工程师方向笔试题

    这套题难啊。。好多坑点。而且想了好久。交卷两小时。。想了一晚上。

    第一题还是不知道怎么dp的。。可能要坑一下明天补。。

    如果有大佬能指点下我就更好了QAQ。我是真的菜。。

    我来补题了哈哈哈哈哈哈哈哈哈!!终于过了


    试题链接:2020校招算法工程师方向笔试题

    5、 外卖小哥的保温箱

    题意:众所周知,美团外卖的口号是:”美团外卖,送啥都快”。身着黄色工作服的骑手作为外卖业务中商家和客户的重要纽带,在工作中,以快速送餐突出业务能力;工作之余,他们会通过玩智力游戏消遣闲暇时光,以反应速度彰显智慧,每位骑手拿出装有货物的保温箱,参赛选手需在最短的时间内用最少的保温箱将货物装好。

    我们把问题简单描述一下:

    1 每个货物占用空间都一模一样

    2 外卖小哥保温箱的最大容量是不一样的,每个保温箱由两个值描述: 保温箱的最大容量 bi ,当前已有货物个数 ai ,(ai<=bi)

    3 货物转移的时候,不必一次性全部转移,每转移一件货物需要花费 1秒 的时间

    题解:我这个题用贪心只过了30%。。而且我花了一晚上时间想怎么dp。。想不出来。

    讨论区大佬说贪心只能得到最优k。QAQ我先坑一下。。明天补吧可能

    终于AC了。感谢gg倾情指导。虽然还是找了半下午的bug//

    这个题是一个背包dp。嗯,我背包dp学的可差了。

    我们用dp[i]来表示当前容量为i时所需要的最少背包数。(货物为goods[],容量为cap[])

    外层需要遍历所有的背包容量,内层来做这个dp处理。(外层这里用i,内层用j来表示)

    此时的状态转移方程也就是dp[j] = min(dp[j],dp[j-cap[i]]+1),

    这里就需要注意到j-cap[i]因为j是从sum_cap遍历到1的。防止负数情况出现,做一个负数为0的处理。

    然后我们这里只是做了使用最少背包数的dp处理。但是并不知道time。time是由货物的转移来决定的。所以我们用一个额外的数组weight[]来表示货物多的。因为转移货物越多,花时间越长,所以保存货物多的情况。

    那我们此时会出现三种情况。

    1、dp[j] < dp[j-cap[i]]+1  当前背包大于,那么直接不处理。因为我们要保证背包最小

    2、dp[j] > dp[j-cap[i]]+1  比当前背包要小,那么更新背包,并且将货物加上。

    3、dp[j] = dp[j-cap[i]]+1  相同的情况,保证留下的货物是最大的。

    背包这个过程进行完以后,进行一个遍历,找最优的k,以及最优k对应留下的背包里的货物总量。

    那么我们所需要的时间t = sum_goods-max_weight啦!!!

    分析就是上面这些,代码可能会更清晰。

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn = 1e5+10;
     4 int n;
     5 
     6 int goods[maxn];
     7 int cap[maxn];
     8 int dp[maxn]; 
     9 int weight[maxn];
    10 
    11 int main(){
    12     cin>>n;
    13     int sum_goods = 0;
    14     int sum_cap = 0;
    15     for(int i = 0;i < n; i++){
    16         cin>>goods[i];
    17         sum_goods += goods[i];
    18     }
    19     for(int i = 0;i < n ; i++){
    20         cin>>cap[i];
    21         sum_cap += cap[i];
    22     }
    23 
    24     memset(dp,0x3f,sizeof(dp));
    25     memset(weight,0,sizeof(weight));
    26 
    27     dp[0] = 0;
    28     weight[0] = 0;
    29     for(int i = 0; i < n ;i++){
    30         //遍历容量dp[j]:容量为j时需要的最少背包数
    31         for(int j = sum_cap; j > 0 ; j--){
    32             int res = max(j-cap[i],0);
    33             //大于直接下一个
    34             if(dp[j] < dp[res]+1)   continue;
    35             //小于,更新一下背包数。并且把货物容量更新
    36             else if(dp[j] > dp[res]+1){
    37                 dp[j] = dp[res]+1;
    38                 weight[j] = weight[res]+goods[i];
    39             }
    40             //相等的时候取货物大的情况
    41             else{
    42                 weight[j] = max(weight[j],weight[res]+goods[i]);
    43             }
    44         }
    45     }
    46 
    47     int k = 0x3f;
    48     int max_weight = 0;
    49 
    50     for(int i = sum_goods; i <= sum_cap; i++){
    51         if(dp[i] < k){
    52             k = dp[i];
    53             max_weight = weight[i];
    54         }
    55         else if(dp[i] == k){
    56             max_weight = max(max_weight,weight[i]);
    57         }
    58     }
    59 
    60     cout<<k<<" "<<sum_goods-max_weight<<endl;
    61 
    62 
    63     return 0;
    64 }
    View Code

      

    6、字符串最长公共前缀

    题意:输入n个字符串(1<=n<=3*102,字符串总长度不超过103,只包含小写字母)

    后面多次查询,每次查询输入两个数字x,y,输出第x个字符串和第y个字符串的最长公共前缀长度。(查询次数不超过102)

    题解:字符串丢进vector.然后输入要比较的两个字符串的索引。(记得有多组数据)

    循环在第二个字符串找第一个字符串的当前字符,然后不停截取就可以了。最后输入前缀的长度即可。

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 vector<string> v;
     5 
     6 int main(){
     7     int n;
     8     cin>>n;
     9     string str;
    10     for( int i = 0 ;i < n ;i++){
    11         cin>>str;
    12         v.push_back(str);
    13     }
    14     int a,b;
    15     while(cin>>a>>b){
    16         a--;b--;
    17         string ans = v[a];
    18         while(v[b].find(ans)){
    19             ans = ans.substr(0,ans.size()-1);
    20         }
    21 
    22         int cnt = ans.size();
    23         cout<<cnt<<endl;
    24     }
    25 
    26     return 0;
    27 }
    View Code

    7、字符串排序

    题意:生活中经常有需要将多个字符串进行排序的需要,比如将美团点评的部分业务名称(外卖、打车、旅游、丽人、美食、结婚、旅游景点、教培、门票、酒店),用拼音表示之后按字母逆序排序。字母逆序指从z到a排序,比如对两个字符串排序时,先比较第一个字母按字母逆序排z在a的前面,当第一个字母一样时再比较第二个字母按字母逆序排,以此类推。特殊情况1)空字符串需排在最前面;2)若一个短字符串是另一个长字符串的前缀则短字符串排在前面。请自行实现代码进行排序,直接调用sort等排序方法将不得分且视为作弊。

    题解:这个主要是理解题意。。我刚开始没看题用sort过了30%?,手写了一个快排。

    然后没注意里面那个前缀的判断,过了40%。。也就是我们需要重写一个比较。你用函数也可以,重载运算符也可以。

    根据它两个条件来就行了。因为是用的升序排列,最后输出要逆序。

    再提一点:字符串输入的处理,我是用判断到','把字符串存储丢进vector.然后再清空字符串继续操作。

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn = 1010;
     4 
     5 vector<string> v;
     6 
     7 bool cmp(string a,string b){
     8     if(a == "")   return true;
     9     if(b.find(a) == 0 && a != b)    return true;
    10     if(a.find(b) == 0 && a != b)    return false;
    11     if(a > b)   return true;
    12 
    13     return false;
    14 }
    15 
    16 void qsort(int left,int right){
    17     string res = v[left];
    18     if(left >= right)  return;
    19     int l = left;
    20     int r = right;
    21     while(l != r){
    22         while(l < r && cmp(res,v[r]) == false){
    23             r--;
    24         }
    25         swap(v[l],v[r]);
    26 
    27         while(l< r && cmp(res,v[l])){
    28             l++;
    29         }
    30         swap(v[l],v[r]);
    31     }
    32 
    33     qsort(left,l-1);
    34     qsort(l+1,right);
    35 }
    36 
    37 int main(){
    38     string s;
    39     cin>>s;
    40     int len = s.size();
    41 
    42     int index = 0;
    43     string str;
    44     v.clear();
    45     while(index <= len){
    46         if(s[index] == ',' || index == len){
    47             v.push_back(str);
    48             str.clear();
    49             index++;
    50         }
    51         else{
    52             str += s[index];
    53             index++;
    54         }
    55     }
    56 
    57     
    58     qsort(0,v.size()-1);
    59     for(int i = v.size()-1;i >0 ;i--){
    60         cout<<v[i]<<",";
    61     }
    62     
    63 
    64     cout<<v[0]<<endl;
    65 
    66     return 0;
    67 }
    View Code

    8、 工作安排

    题意:小美是团队的负责人,需要为团队制定工作的计划,以帮助团队产出最大的价值。

    每周团队都会有两项候选的任务,其中一项为简单任务,一项为复杂任务,两项任务都能在一周内完成。第i周,团队完成简单任务的价值为li,完成复杂任务的价值为hi。由于复杂任务本身的技术难度较高,团队如果在第i周选择执行复杂任务的话,需要在i-1周不做任何任务专心准备。如果团队在第i周选择执行简单任务的话,不需要提前做任何准备。

    现在小美的团队收到了未来N周的候选任务列表,请帮助小美确定每周的工作安排使得团队的工作价值最大。

    题解:哎,上去贪心也是30%。后面发现不是。。是个比较简单的dp。

    思考一下两个状态。我们需要用两周的时间做判断。

    1、做两周的简单工作。  easy[i-1] + easy[i]

    2、准备一周,做一周的难工作。  diff[i]

    这一周的状态是由前两周来决定,。

    所以可以得到状态转移方程dp[i] = max(dp[i-1] + easy[i],dp[i-2] + diff[i])

    初始化的时候记得dp[0]和dp[1]都要初始化掉,

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn = 1010;
     4 
     5 int easy[maxn];
     6 int diff[maxn];
     7 int dp[maxn];
     8 
     9 int main(){
    10     int n;
    11     cin>>n;
    12     for(int i = 0 ;i < n ;i++){
    13         cin>>easy[i]>>diff[i];
    14     }
    15     dp[0] = max(easy[0],diff[0]);
    16     dp[1] = max(dp[0]+easy[1],diff[1]);
    17 
    18     for(int i = 2;i <= n; i++){
    19         dp[i] = max(dp[i-1]+easy[i],dp[i-2]+diff[i]);
    20     }
    21     cout<<dp[n-1]<<endl;
    22 
    23     return 0;
    24 }
    View Code
  • 相关阅读:
    滚动条滚动方向
    阶乘函数-尾递归
    返回顶部
    CommonJS
    vuessr
    随机字符串
    indexedDB
    深层次选择器
    Vue3.0简单替代Vuex
    shell 学习笔记
  • 原文地址:https://www.cnblogs.com/Asumi/p/12543602.html
Copyright © 2011-2022 走看看