位元組跳動_暑期實習面試
時間:2020年6月29日--2020年7月10日
地點:線上
面試機會的取得
一、得知活動
是通過位元組跳動“玩轉客戶端”活動得到的推薦獲得的面試機會。
面試的經過
一、一面
時間:2020年6月29日 17:30
地點:線上
-
自我介紹/交流
-
聊比賽/訓練經歷居多
-
知識點考察
-
面試中的筆試題
輸入英語句子,將單詞逐個反轉然後輸出。
樣例輸入: Yummy! What is it made of?
樣例輸出: ymmuY! tahW si ti edam fo?
其實這是簡單題了,在ACM的比賽中只是簽到題的水平,但在面試的過程中還是有挺多需要講究的。
-
面試時的程式碼
#include <iostream> #include <string> using namespace std; int main(){ string str; ios::sync_with_stdio(false); while(cin>>str){ int len = str.length(); if(str[len-1]=='!'||str[len-1]=='.'||str[len-1]==','||str[len-1]=='?'){ for(int i=len-2;i>=0;i--) cout<<str[i]; cout<<str[len-1]<<' '; } else { for(int i=len-1;i>=0;i--) cout<<str[i]; cout<<' '; } } return 0; }
-
其實上面的程式碼明顯還是有很多問題的,首先我不能保證輸入是規範的,我不知道標點符號後面是否一定會帶空格。其次,英文的標點符號肯定是不止我所列舉的這些。雖然說這與題目不夠規範也有關係,但是面試出題者肯定也想考核我們思考問題的全面性。
-
面試後的改進
// 採用先進後出的棧結構,更符合此題的思路 #include <cstdio> #include <vector> using namespace std; bool isAlphabet(char c){ return (c>='a' && c<='z') || (c>='A' && c<='Z'); } int main(){ char c; vector<char> v; while(~scanf("%c",&c)){ if(c == '\n') break; if(isAlphabet(c)){ v.push_back(c); } else { while (!v.empty()) { printf("%c",v.back()); v.pop_back(); } printf("%c",c); } } return 0; }
-
二、二面
-
這次沒有自我介紹
-
知識點考察
-
c++語法基礎
智慧指標/static const等關鍵字修飾函式的作用/volatile關鍵字/stl庫底層原始碼實現
-
計算機網路
http協議的具體細節
-
-
面試中的筆試題
輸入一個數字,輸出其各位數字排列組合下一大的數
樣例輸入: 12654
樣例輸出: 14256
這個的思路就是從後往前找第一個小於最後一個數的數,然後把最後一個數插到它前面,並且對它後面的數進行升序排序。(這裡的它都是指第一個小於最後一個數的數)
#include <algorithm> #include <iostream> #include <string> #include <set> using namespace std; #define setiter set<int>::iterator string findNxt(string a){ string temp; char back = a.back(); a.pop_back(); while(!a.empty()){ auto t = a.back(); temp.push_back(t); a.pop_back(); if(t<back) break; } a.push_back(back); a.push_back(temp.back()); temp.pop_back(); sort(temp.rbegin(), temp.rend()); while(!temp.empty()) { a.push_back(temp.back()); temp.pop_back(); } return a; } int main(){ string str = "12654"; cout<<findNxt(str)<<endl; return 0; }
三、三面
-
自我介紹
-
知識點考察
- c++語法基礎
- 計算機網路
-
聊實際應用中的前端瀏覽體驗改善
-
聊之前的專案做了什麼,有什麼還要改進的地方
-
面試中的非筆試題
25匹馬,5個跑道,每次只能跑5匹,用最少的次數選出最快的前3匹?
(備註:沒有秒錶,只能知道馬的先後順序)
這道題我以前是沒有接觸過的,所以只能臨場發揮,還好最後還是回答上了正確答案。
Step 1:
把馬隨機分成5組,每組5匹,分別進行賽跑,共需5次
Step 2:
取前5次比賽各自的第1名出來,組成1組,進行賽跑,共1次
Step3:
取Step2那次比賽的第2名和第3名、第1名在Step1所在的組的第2名和第3名、第2名在Step2所在組的第2名,組成1組,進行賽跑,共1次
所以總共7次可以選出最快的前3匹
-
面試中的筆試題
輸入兩個連結串列,一個升序、一個降序,合併成一個升序連結串列。
樣例輸入: 2->6->8->9、10->7->3
樣例輸出: 2->3->6->7->8->9->10
其實這挺簡單的,就是連結串列不熟悉,所以沒有答上來,後來還是面試官換了一道題。面試後的補題:
#include<iostream> using namespace std; struct Node{ Node* next = NULL; int value = 0; }; Node* ReadALink(int m) { bool isHead=1; Node *head,*newp,*oldp; newp = oldp =new Node; cin>>newp->value; head = newp; while(m--){ if(isHead) isHead = 0; else oldp->next = newp; oldp = newp; newp = new Node; cin>>newp->value; } oldp->next = newp; newp->next = NULL; return head; } Node* ReverseALink(Node* head) { if (head == NULL || head->next == NULL) return head; Node *newhead = head, *nxt = head->next; newhead->next = NULL; while(nxt != NULL) { Node *iter = nxt-> next; nxt->next = newhead; newhead = nxt; nxt = iter; } return newhead; } Node* MergeLinks(Node* head1,Node* head2) { Node *p,*newhead=NULL,*t=new Node; while(head1&&head2) { if(head1->value<head2->value) { p=head1; head1=head1->next; } else { p=head2; head2=head2->next; } if(!newhead) newhead=t=p; else{ t=t->next=p; p->next=NULL; } } t->next = head1?head1:head2; return newhead; } int main(){ int m,k; cin>>m>>k; Node* headup = ReadALink(m-1); Node* headdown = ReadALink(k-1); Node* headnew = ReverseALink(headdown); Node* ans = MergeLinks(headnew,headup); while(ans->next != NULL){ cout<<ans->value<<' '; ans = ans->next; } cout<<ans->value<<endl; return 0; }
輸入一個數組,找到所有合為100的組合,數字重複的組合不算,詢問組合數量。
樣例輸入: 1 2 3 3 27 97 97 99 100
樣例輸出: 2
這道也是簡單題,但是後來面試官問我怎麼優化空間複雜度的時候我腦子沒有轉過來,直接回答那就兩個for迴圈吧。先給出面試時的程式碼:
#include<iostream> using namespace std; int findAndIsH(int* a,int len){ bool vis[101] = {0}; bool find[101] = {0}; int cnt = 0; for(int i=0;i<len;i++){ if(vis[a[i]]) continue; vis[a[i]] = 1; if(find[a[i]]){ cnt++; } else { find[100-a[i]] = 1; } } return cnt; } int main(){ int a[10] = {1,2,3,3,27,97,97,99,100}; cout<<findAndIsH(a,9)<<endl; return 0; }
後來改的程式碼(優化了時間複雜度),在修改的過程中我還發現了上面的做法還有一個問題,就是如果是50、50就考慮不到了:
#include <iostream> #include <cstring> #include <set> using namespace std; #define setiter set<int>::iterator int findAndIsH(int* a,int len){ set<int> s; // int cnt[51]={0}; int ans = 0; for(int i=0;i<len;i++){ s.insert(a[i]); } setiter l = s.begin(); setiter r = s.end(); while(l!=r) { if(*l == 100-*r){ ans++; l++; r--; } else if(*l < 100-*r){ l++; } else{ r--; } } /* for(set<int>::iterator iter=s.begin();iter!=s.end();iter++){ int re = *iter<50?*iter:100-*iter; cnt[re]++; } for(int i=0;i<51;i++){ if(cnt[i]>1) ans++; } */ return ans; } int main(){ int a[10] = {1,2,3,3,27,97,97,99,100}; cout<<findAndIsH(a,9)<<endl; return 0; }
由於在讓我優化空間複雜時我扯了一下用map,然後就被考到了map的空間複雜度和map的底層實現。
-
聊自己的優點和缺點
面試的總結
雖然是涼經,當整體來說位元組的面試過程還是很舒適的吧,相信只要簡歷不要寫得太飄,應該就不會被重重地拷打一番。
然後說一下面試的等待時間吧。一面的結果等了大概一星期吧,二面的結果大概兩天就出了,三面也是兩天出了結果。
最後祝福大家可以面到想要的工作。