【美团点评】2020校招数据分析方向笔试题

这几天做了下美团校招的一些套题。(只写了编程,这两天慢慢更新吧)

 

这套题还是蛮简单的。。我暴力了好几个都能过。一个小时多一点差不多能写完。


 

试题链接:美团点评2020校招数据分析方向笔试题

 

4、棋子翻转

题意:在4*4的棋盘上摆满了黑白棋子,黑白两色的位置和数目随机其中左上角坐标为(1,1),右下角坐标为(4,4),现在依次有一些翻转操作,要对一些给定支点坐标为中心的上下左右四个棋子的颜色进行翻转,请计算出翻转后的棋盘颜色。

 

题解:这题有点坑,输入输出数据类型都是字符串,我可能leetcode刷多了以为是vector然后一直报段错误。

我用了极其暴力的手法做了输入的处理。。因为这个字符串是固定了长度的。。所以。。看代码吧。

 

代码:

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int mp[5][5];
 4 int pos[4][4];
 5 string s;
 6 string p;
 7 
 8 void init(){
 9     cin>>s;
10     cin>>p;
11     mp[0][0] = s[2]-'0';
12     mp[0][1] = s[4]-'0';
13     mp[0][2] = s[6]-'0';
14     mp[0][3] = s[8]-'0';
15 
16     mp[1][0] = s[12]-'0';
17     mp[1][1] = s[14]-'0';
18     mp[1][2] = s[16]-'0';
19     mp[1][3] = s[18]-'0';
20 
21     mp[2][0] = s[22]-'0';
22     mp[2][1] = s[24]-'0';
23     mp[2][2] = s[26]-'0';
24     mp[2][3] = s[28]-'0';
25 
26     mp[3][0] = s[32]-'0';
27     mp[3][1] = s[34]-'0';
28     mp[3][2] = s[36]-'0';
29     mp[3][3] = s[38]-'0';
30 
31     pos[0][0] = p[2]-'0';
32     pos[0][1] = p[4]-'0';
33 
34     pos[1][0] = p[8]-'0';
35     pos[1][1] = p[10]-'0';
36 
37     pos[2][0] = p[14]-'0';
38     pos[2][1] = p[16]-'0';
39 
40 }
41 
42 int main(){
43     init();
44     int x,y;
45     for(int i = 0; i < 3; i++){
46         x = pos[i][0];
47         y = pos[i][1];
48         x--;y--;
49         if(x-1 >= 0)
50             mp[x-1][y] = !mp[x-1][y];
51         if(x+1 < 4)
52             mp[x+1][y] = !mp[x+1][y];
53         if(y-1 >= 0)
54             mp[x][y-1] = !mp[x][y-1];
55         if(y+1 < 4)
56             mp[x][y+1] = !mp[x][y+1];
57     }
58     cout<<"[";
59     for(int i = 0 ;i < 4;i++){
60         cout<<"[";
61         for(int j = 0; j < 3 ;j++){
62             cout<<mp[i][j]<<",";
63         }
64         if(i == 3)  cout<<mp[i][3]<<"]";
65         else    cout<<mp[i][3]<<"],";
66     }
67     cout<<"]"<<endl;
68     
69     return 0;
70 }
View Code

 

 

 

5、寻找最后的山峰

题意:山峰元素是指其值大于或等于左右相邻值的元素。给定一个输入数组nums,任意两个相邻元素值不相等,数组可能包含多个山峰。找到索引最大的那个山峰元素并返回其索引。假设 nums[-1] = nums[n] = -∞。

 

题解:感觉也是一个模拟。。一次循环,判断一下左右,满不满足条件。因为是找索引最大。。遍历完就行了。

最后找一个特判,就是最后一个数是不是大于左边的数就可以了。

优化当然也是可以,用二分可行。

 

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3  
 4 vector<int> num;
 5 int main(){
 6     int n;
 7     while(cin>>n){
 8         num.push_back(n);
 9     }
10      
11     int len = num.size();
12     int pos = 0;
13     for(int i = 1 ;i < len-1; i++){
14         if(num[i]>=num[i+1] && num[i]>=num[i-1]){
15             pos = i;
16         }
17     }
18        
19     if(num[len-1] > num[len-2])    pos = len-1;
20     cout<<pos<<endl;
21      
22     return 0;
23 }
View Code

 

 

6、比大小

题意:给定一个整数数组,返回一个数组。该返回数组中第i个数字为,原数组中第i个位置的数字至少往右走多少步才能遇到比它大的数字。如果遇不到或者已经处于最右的位置,则置为-1。

 

题解:这个题暴力是会超时的。做优化。参考了一下讨论区大佬的代码,用单调栈做处理。

这样每次比较栈顶元素和当前元素,我们保存栈顶元素的这个步数就好了,也就是找栈顶的大元素。

友情提示:切c++14编译器。

 

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 1e6+10;
 4 
 5 int num[maxn];
 6 int ans[maxn]={0};
 7 int main(){
 8     int n;
 9     cin>>n;
10     for(int i = 0; i < n ;i++){
11         cin>>num[i];
12         ans[i] = -1;
13     }
14     stack<int> s;
15     
16     int cnt = 0;
17     while(cnt < n){
18         if(!s.empty() && num[s.top()] < num[cnt]){
19             int xx = s.top();
20             s.pop();
21             ans[xx] = cnt - xx;
22         }
23         else{
24             s.push(cnt);
25             cnt++;
26         }
27     }
28 
29     for(int i = 0; i < n ;i++){
30         cout<<ans[i]<<endl;
31     }
32     
33     return 0;
34 }
View Code

 

 

7、关联查询

题意:数据对象data1List,员工表,存储员工ID,员工姓名

数据对象data2List, 员工工作时长表,存储员工ID,月份,工时

计算每个员工1-3月每月工时及总工时

 

题解:我好像做复杂了。。就是一个模拟题。。我甚至怀疑只有一组数据。。理解题意就行了。

 

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 1010;
 4 
 5 map<string,int> mp;
 6 
 7 struct member{
 8     int id;
 9     string name;
10     int sumtime;
11 };
12 
13 member peo[maxn];
14 
15 int main(){
16     int cnt = 0;
17     while(cin>>peo[cnt].id>>peo[cnt].name){
18         int id;
19         string month;
20         int time;
21         cin>>id;
22         for(int i = 0; i < 3; i++){
23             cin>>month>>time;
24             mp[month] = time;
25         }
26         peo[cnt].sumtime = mp["01"]+mp["02"]+mp["03"];
27         cout<<peo[cnt].name<<" "<<mp["01"]<<" "<<mp["02"]<<" "<<mp["03"]<<" "<<peo[cnt].sumtime<<endl;
28         cnt++;
29     }
30  
31     
32     return 0;
33 }
View Code

 

 

8、滑动窗口的中位数

题意:在实时计算中,数据流源源不断地流入计算单元,经常需要借助窗口来处理数据,其中有一类窗口为滑动窗口(Sliding Window),其特点是窗口长度固定,每次滑动一定的位移(slide)

 

 

 

现给定一个数组 nums,有一个长度为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。注意你只可以看到在滑动窗口 k 内的数字,滑动位移大小slide=1,即滑动窗口每次只向右移动一位。

要求返回每一个滑动窗口内的中位数,解释中位数定义,例如:对于[2,3,4],中位数是3;对于[2,3],中位数是 (2 + 3) / 2 = 2.5

注意:为了简化窗口计算,规定如果没有累计到窗口大小的数,不能触发计算,即不输出结果!

 

题解:暴力可过。每次对窗口里的元素排序,得到中位数即可。

 

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 1010;
 4  
 5 double num[maxn];
 6 vector<double> res;
 7 int main(){
 8     int n,k;
 9     cin>>n>>k;
10     for(int i = 0; i < n; i++){
11         cin>>num[i];
12     }
13     int flag = 0;
14     if(k%2)    flag = 1;
15      
16     for(int i = 0; i <= n-k; i++){
17         for( int j = i; j < i+k ;j++){
18             res.push_back(num[j]);
19         }
20         sort(res.begin(),res.end());
21          
22         if(flag)    num[i] = res[k/2];
23         else    num[i] = (res[k/2 - 1] + res[k/2]) / 2;
24          
25         res.clear();
26     }
27      
28     for(int i = 0; i <= n-k; i++){
29         printf("%.1lf ",num[i]);
30     }
31      
32     return 0;
33 }
View Code

 

 

9、月份天数

题意:输入年份月份,请输出这个月的天数

 

题解:也是个做了很多遍的题。判断闰年。

闰年:1、能被4整除但是不能被100整除。2、能被400整除。

满足以上条件随便一个就行。

 

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3  
 4 bool judge(int year){
 5     if(year%4 == 0 && year%100)    return true;
 6     if(year%400 == 0)    return true;
 7      
 8     return false;
 9 }
10  
11 int main(){
12     int year,month;
13     while(cin>>year>>month){
14         int flag = 0;
15         if(judge(year))    flag = 1;
16         if(month == 1 || month == 3 || month == 5 || month == 7||
17            month == 8 || month == 10 || month == 12){
18             cout<<31<<endl;
19         }
20         else if(month == 2){
21             if(flag)    cout<<29<<endl;
22             else    cout<<28<<endl;
23         }
24         else cout<<30<<endl;
25     }
26     return 0;
27 }
View Code

 

 

10、整数分解

题意:一个正整数N可以分解为M(M>1)个正整数的和,即N=K+L,例如N=5、M=2时可以分解为(1+4,2+3)。

给定一个正整数N(1<N<200)及正整数M(1<M<200),求有多少种可能的分解组合(注:K+L和L+K算一种)

 

题解:整数分解也是比较经典的题目。一般我会先用dfs,再用dp。

= =牛客这个编译器有毒,dfs得用c写才行。要不然报段错误。dfs超时,dp应该是正解。

但是都不给AC。我看讨论区也没人过,应该题目有点问题。。

我会给出两份代码。

1、dfs。普通爆搜一定会超时,所以这里说的dfs是做了剪枝处理的。枚举的时候从上一次的划分枚举到sum+i*(m-cur)<=n,因为后面再继续划分一定会大于当前所用分数。所以直接剪枝而不是枚举到n。

2、dp。dp[i][j]表示i可以分成j份的方案。i中分j份可以为:i-1中分j-1份,和i-j中分j份。

初始化只需要做一个dp[0][0]=1。

 

代码:

 1 //深搜
 2 #include<bits/stdc++.h>
 3 using namespace std;
 4 int n,m;
 5 int cnt = 0;
 6 
 7 
 8 void dfs(int res,int sum,int cur){
 9     if(cur == m){
10         if(sum == n) cnt++;
11         return;
12     }
13     for(int i = res; sum+i*(m-cur)<=n ; i++){
14         dfs(i,sum+i,cur+1);
15     }
16 
17 }
18 int main(){
19     cin>>n>>m;
20     dfs(1,0,0);
21     cout<<cnt<<endl;
22 
23 
24     return 0;
25 }
26 
27 
28 
29 //dp
30 #include<bits/stdc++.h>
31 using namespace std;
32 const int maxn = 210;
33 int n,m;
34 int dp[maxn][maxn]={0};
35 
36 int main(){
37     cin>>n>>m;
38     dp[0][0] = 1;
39 
40     for(int i = 1; i <= n ;i++){
41         for(int j = 1; j <= m ;j++){
42             dp[i][j] += dp[i-1][j-1];
43             if(i>=j) dp[i][j]+=dp[i-j][j];
44         }
45     }
46 
47     cout<<dp[n][m]<<endl;
48 
49     return 0;
50 }
View Code

 

posted @ 2020-03-19 01:12  甜酒果。  阅读(2564)  评论(2编辑  收藏  举报