轩_雨

青山不厌三杯酒,长日惟消一局棋
字节跳动_暑期实习面试

时间: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的底层实现。

  • 聊自己的优点和缺点

面试的总结

虽然是凉经,当整体来说字节的面试过程还是很舒适的吧,相信只要简历不要写得太飘,应该就不会被重重地拷打一番。

然后说一下面试的等待时间吧。一面的结果等了大概一星期吧,二面的结果大概两天就出了,三面也是两天出了结果。

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

posted on 2020-07-21 15:11  轩_雨  阅读(580)  评论(0编辑  收藏  举报