【美團點評】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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM