1. 程式人生 > 實用技巧 >位元組跳動_暑期實習面試

位元組跳動_暑期實習面試

時間: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的底層實現。

  • 聊自己的優點和缺點

面試的總結

雖然是涼經,當整體來說位元組的面試過程還是很舒適的吧,相信只要簡歷不要寫得太飄,應該就不會被重重地拷打一番。

然後說一下面試的等待時間吧。一面的結果等了大概一星期吧,二面的結果大概兩天就出了,三面也是兩天出了結果。

最後祝福大家可以面到想要的工作。