【美团点评】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 }
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 }
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 }
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 }
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 }
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 }
10、整数分解
题意:一个正整数N可以分解为M(M>1)个正整数的和,即N=K+L,例如N=5、M=2时可以分解为(1+4,2+3)。
题解:整数分解也是比较经典的题目。一般我会先用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 }