字节跳动五轮技术面终于收获意向书(后端开发)

字节是我秋招提前批第一个投的,从7.26一面到今天9.7拿意向书,耗时40余天,历经五轮技术面,期间心情跌宕起伏,用此面经纪念一下这段心跳回忆

产品研发与工程化部门

一面

7.26 70min

个人介绍3min

针对项目提问20min

先问我哪项了解多点,我说计算机网络,然后面试官说那先问一下简单的操作系统吧(-_-


进程线程协程区别

A进程可以访问B进程的空间吗(不能

那怎么能访问呢(IPC

共享内存咋实现的(直接把物理地址映射到另一个进程的地址空间里面去

为啥共享内存快(省略了用户态到内核态的开销,追问还有吗,回答其他的不了解了)


TCP三次握手,服务端如果不调用accept会咋样(客户端发完第三次的ack包后就认为自己建立连接,而服务端不认为

那为什么会有这种状态不一致呢(拜占庭问题

TCP是可靠的,三次握手能解决什么问题呢,用你的观点来说好像不是可靠的?(建立连接的确可能出现这种问题,但是客户端第一次发包的时候,服务端认为连接不存在,返回一个RST包,这样客户端就知道连接不存在了

那我换个问题,TCP双方确立连接后正常发送数据,如果服务端突然崩了,那会咋样(客户端认为连接还在,服务端认为不存在,返回RST包提醒客户端

假设服务端进程core了,或者机器坏掉了,这两种有区别吗(第一种是返回RST包,第二种不会有任何响应,客户端会重试几次,然后认为连接失效

RST包是谁发起(服务端

是指这个进程还是这个机器呢(应该是这台机器吧,因为这个进程已经core掉了

那你知道这个包的协议是什么,就是它在哪一层(RST包就是TCP包吧,那不就是在传输层?

连接都断了,为什么还有这个包发送呢(我回答的是Linux TCP协议栈可以处理这种问题,我没有这个连接,莫名其妙接收到了这个连接的包,所以会回一个RST包

你意思说这还是一个TCP包是吧(对

面试官沉默ing,这让我产生了怀疑,RST包不是TCP包嘛?


共识算法了解哪些呢(paxos、raft、gossip,前面稍微连接一点

raft大概是咋样的逻辑(更好实现更好理解,leader、follower、candidate,相比于paxos,选主和日志复制分离,模块化,paxos的proposer和acceptor把选主和日志复制糅合在一起了

你知道它是怎么解决网络分区的问题(脑裂的问题,一半以上的支持才会确认自己leader,好像是通过item的index来决定谁的leader程度更高,另一个就自动退化为follower


C++虚函数说一下

如何取到子类的函数地址(虚函数表其实是个数组,对虚指针解引用,然后用中括号


MySQL索引(B树、B+树

为啥用B+树(减少磁盘IO次数,区间遍历

写性能相比于读性能(要差,因为要分裂和合并分支,来维持m阶的特性


下面的输出

class C {
        public:
            // int a;
            void func(void) {
                printf("hello %d", a);
            }
    };
    int main() {
            C *c = NULL;
            c->func();
        return 0;
    }

我首先说是会报member access null类似的错,然后面试官让我跑一下,啪啪打脸。。

再分析一下?(想了一会,推断说func是非虚的成员方法,所以可以直接访问

那怎么找到func的地址,或者说这个函数是放在哪里的(代码段

如果加上一个int a成员变量,会输出什么?(先想了一会,开玩笑说对自己的答案不是很自信,我首先说会输出0,然后再改口说会报错,原因是func调用了成员变量,成员变量需要访问类的对象,而c没有new出来,所以会报错,大概是对的


用rand 7 实现 rand 10


有一个无序整型数组:[3, 7, 2, 0, -1, 9, 8 ...],长度1000w左右,要求设计一个算法,找到数组中位数

先说了大小堆的联机解法,然后面试官说想要小于O(nlogn)时间复杂度的排序,对数组元素没要求,也不需要额外空间

这里我们的沟通出现了问题,我以为面试官是想要完全排序,然后说了桶排序什么的,但他原意是找到中位数就行,害,那就直接进入主题:快速选择

14min左右撸出来了,没时间debug,跑出来是死循环,然后时间也差不多了,大概说了一下思路,差不多解释清楚了

#include 
#include 
using namespace std;
int quickSelect(vector &vec, int l, int r) {
    if (l >= r) return l;
    int pivot = l; // 选择第一个为枢纽
    ++l;
    while (l < r) {
        while (l < r && vec[l] < vec[pivot]) ++l;
        while (l  vec[pivot]) --r;
        swap(vec[l], vec[r]);
    }
    swap(vec[l], vec[pivot]); // 枢纽归位
    return l; // 将pivot返回
}
int findMedium(vector &vec) {
    int n = vec.size();
    int l = 0;
    int r = n - 1;
    int k;
    while (true) {
        k = quickSelect(vec, l, r);
        if (k == n / 2) { // 找到中位数了
            return vec[k];
        } else if (k < n / 2) {
            l = k; // 中位数在右边
        } else {
            r = k; // 中位数在左边
        }
    }
    return -1; // never reached
}
int main() {
    vector vec {3, 7, 2, 0, -1, 9, 8};
    cout << findMedium(vec) << endl;
}

过了几天后hr约时间,我说到最近在实习,能否周末,hr说要尽快走完,可以安排二面三面在同一天

二面

90min

项目

两段实习

elk、日志的难点,采集日志的进程挂了咋办,日志rotate后咋办(不是很会

c++内存模型(高字节到低字节整了个遍

malloc的底层实现(brk与mmap

虚拟内存

io复用

tcp拥塞控制

题目:二维数组的地图中,搜索指定字符串是否存在

同力扣79,力扣79还加了限制条件,已经走过的单元格不能再走,得用visited数组记录

#include 
#include 
using namespace std;
bool dfs(vector> &board, string &word, int wordIndex, int x, int y) {
    if (board[x][y] != word[wordIndex]) {
        return false;
    }
    if (word.size() - 1 == wordIndex) {
        return true;
    }
    wordIndex++;
    if ((x > 0 && dfs(board, word, wordIndex, x - 1, y))
        || (y > 0 && dfs(board, word, wordIndex, x, y - 1))
        || (x < board.size() - 1 && dfs(board, word, wordIndex, x + 1, y))
        || (y < board[0].size() - 1 && dfs(board, word, wordIndex, x, y + 1))
        ) {
        return true;
    }
    return false;
}
bool exist(vector> &board, string word) {
    for (int i = 0; i < board.size(); ++i) {
        for (int j = 0; j < board[0].size(); ++j) {
            if (dfs(board, word, 0, i, j)) {
                return true;
            }
        }
    }
    return false;
}
int main() {
    vector> map;
    vector vec = {'a', 'c', 'd', 'z'};
    map.push_back(vec);
    vec = {'x', 't', 'r', 'o'};
    map.push_back(vec);
    vec = {'f', 'i', 'o', 'o'};
    map.push_back(vec);
    string str = "zoo";
    cout << exist(map, str) << endl;
    str = "zoro";
    cout << exist(map, str) << endl;
    str = "xtifx";
    cout << exist(map, str) << endl;
    str = "oto";
    cout << exist(map, str) << endl;
}

题目:给定m个字符 [a, b, c, d],字符可能重复,以及一个长度为n的字符串tbcacbdata,问能否在这个字符串中找到一个长度为m的连续子串,使得这个子串刚好由上面m个字符组成,顺序无所谓,返回任意满足条件的一个子串的起始位置,未找到返回-1。

输入 [a, b, c, d] + tbcacbdata -> 3

输入 [a, b, c, c] + tbcacbdata -> 1

输入 [a, b, c, d] + abctbcdata -> 4

同力扣438

#include 
#include 
using namespace std;
int func(string s, string p) {
    int res;
    int count[256] = {0};
    int l = 0;
    int r = 0;
    int len = 0;
    for (auto &e : p) ++count[e];
    while (r < s.size()) {
        if (--count[s[r++]] >= 0 && ++len == p.size()) {
            res = l; // 匹配命中
            return res;
        }
        if (r - l == p.size() && ++count[s[l++]] > 0) --len;
        //++l; // 每次左指针收缩一格,进入下一轮循环
    }
    return res;
}
int main() {
    string str = "tbcacbdata";
    string pattern = "abcd";
    cout << func(str, pattern) << endl;
    pattern = "abcc";
    cout << func(str, pattern) << endl;
    str = "abctbcdata";
    pattern = "abcd";
    cout << func(str, pattern) << endl;
}

最后反问环节我问面试官后面是不是还有三面,面试官说他不知道,顿感凉凉,但是面完不久后就收到hr电话,晚上三面

三面

这里相当于就是主管了,看得出来,面试官是个大佬,说话云淡风轻,问的东西都很深入

70min

Raft的Leader挂了咋办

Paxos原理

科研方向,软件定义网络是什么

实习经历

异步队列用的是什么(MQ),你对MQ的原理熟悉吗(还没深入了解,实习时间不久,先把组内架构摸清楚,还没深入了解中间件


A与B轮流从 1000 个棋子里取棋子,规定每次最多取 7 个,最少取 1 个,谁最后取完剩下的棋子谁获胜,A先取,有没有必胜的策略?

刚开始算错了,1000除以8的余数是4。。。

其实是0,后来再思考了一会,给出了答案:如果B足够聪明,A必输


有一个很大很大的输入流,大到没有存储器可以将其存储下来,也不知道到底有多大,而且只输入一次,如何从这个输入流中随机取得 7 个记录。

蓄水池算法


class A {
public:
    A(int v) {
        _v = v;
    }
    void Run() {
        std::cout << "Hello" << std::endl;
    }
private:
    int _v;
}
int main() {
    A * p = NULL;
    p->Run();
}

扯了一下内存模型,应该是不会报错的

如果Run里面输出_v呢?(会报错

如果Run是虚函数呢?(会报错

面试完后本地跑了一下,是这样的


struct Obj {
    char a;
    uint32_t b;
    uint8_t c;
    uint64_t d[0];
};
sizeof(Obj) = ?

字节对其的知识点有点忘了,这题不是很会,猜了个1+4+8=13,面试官说ok,下一题,我问这是对的吗,他干脆利落地说:不对

(害,这问啥呢,打击自信心啊

最后反问面试官环节问了一下这题是怎么做的,面试官很耐心的给出了解释

如果没有第四个字段,应该是4+4+4=12,加上第四个字段是16,第四个字段不占空间,但会告诉编译器要按8字节对齐

这种用法在内核里经常用到,比如下面可以直接用下标访问

Obj o1;
uint64_t array[1024]; // 在内存中,array紧跟o1后面
o1.d[123]; // 可以访问array的元素

实现一个函数,删除所有 map 中 val 为 100 的元素

void RemoveElement(map &elems, int target) {
    for (auto it = elems.begin(); it != elems.end(); ) {
        if (it->second == target) {
            it = elems.erase(it);
        } else {
            ++it;
        }
    }
}

给定一个字符串 s ,找出 至多 包含 k 个不同字符的最长子串 T ,输出子串 T 长度。

示例 1:
输入: s = "eceba", k = 2
输出: 3
解释: 则 T 为 "ece",所以长度为 3。

示例 2:
输入: s = "aa", k = 1
输出: 2
解释: 则 T 为 "aa",所以长度为 2

int func(string s, int k) {
    unordered_map m;
    int maxLen = 0;
    int i = 0; // 快指针
    int j = 0; // 慢指针
    while (i < s.size()) {
        if (m.size() <= k) m[s[i]]++;
        while (m.size() > k) { // 当前区间不满足『至多包含k个不同字符』
            if (--m[s[j]] == 0) {
                m.erase(s[j]);
            }
            ++j; // 慢指针左移
        }
        maxLen = max(maxLen, i - j + 1);
        ++i; // 快指针左移
    }
    return maxLen;
}

大概用了不到20分钟撸完了,自己造测试用例也通过了,面试官还有点嫌我慢了(-_-


过了几天收到hr电话,说我前面三面表现不错,可以加面一轮,开始被虐了。。

四面

交叉面 78min

面试官上来先介绍了一下,这是交叉面,介绍了一下自己所在的部门,还主动说了自己的名字(心里想着,是不是会稍微简单一点呢,后来啪啪打脸,不过也有可能是因为我菜吧

首先问了下阿里的实习内容,详细问了我的工作内容,还问了一下我的工作难点是什么

再询问了腾讯的实习内容

系统调用read的流程(用户态切到内核态,磁盘驱动器,通过LBA找到块位置,读到内存缓冲区,再拷贝到用户进程里面)

有什么优化方法吗(DMA、还有零拷贝技术,比如mmap, sendfile,还有写时复制技术)

gdb调试,gdb怎么调试运行的进程?(gdb attach pid),gdb调试正在运行的进程,如果你还给它发RPC会怎么样(这里没太理解的他的意思,意思是多线程,就一个线程停在断点上)


北京小汽车摇号,20万人,每个人的初始权重都是一样的,但有人没被摇中,他的权重就会增加,用计算机的语言来解决这个问题(口述代码思路)

我想到每个人维护一个int值,初始为1,没有摇中就增加1,下次摇号时,把所有人的计数值在数轴上展开,比如第一个人权重为1,那他就占1,第二个权重未3,那他就占2,3,4,然后调用一次rand函数

面试官说明白我的意思,但不满意这个解法,提示说,能不能不存下来,但是每个人按宽度对应到坐标轴上去,想了很久,想不出来


int * arr N 大根堆
del k, 数组下标k

坦白:我只知道最大堆的一些特点,比如一个节点下标为i,他的左儿子节点下标是2i,他的右儿子节点下标是2i+1,他的父亲节点下标是i/2,然后增加和删除需要一些上滤和下滤操作,但是我没自己实现过


最后面试官说ok,再换一道,让我用C++实现一个线程池,我说可能有的api不太记得完整的,面试官说没关系,能写多少是多少

大概写了有15min,然后面试官说由于时间关系就到这里吧,我大概明白你的(代码)的意思了,我没啥其他问题了,你有什么想问我的吗

解释了一下今天表现不是特别好,正好问到薄弱的地方,面试官说没关系,问了下对方的base与部门,是北京的推荐工程化落地的


四面完后几天就没下文了,心境凄凉,等了一个多星期,才有hr联系我说,争取了机会,再加面一轮,又有希望了!

五面

8.23 50min

阿里转正了吗,怎么看字节和阿里

前面四轮技术面都问了很多了,就问你一个简历上的东西吧

quic为什么可以队头不阻塞(各流独立blabla,答的不算特别完整

概率题:一种流行病患病概率是1%,有一种检测试纸,检测的准确率是99%,我现在试纸检测阳性了,请问我患病的概率有多大?(数学题,条件概率,贝叶斯公式

逻辑题:

  1. 给你一个天平,32个重量不一样的石头,要比较多少次才能找到最重的石头(31次
  2. 基于问题1,你已经找到最重的石头了,如何找到第二重的石头,还需要比较吗,还需要比较多少次?(类似于欧冠32强,画一个冠军的晋级路线图,实力最强的肯定是冠军,但亚军不一定是实力第二强的,总之:冠军这一路上碰到的队伍都有可能是实力第二强的队伍,所以五支队伍中选出最强的,需要4次)
  3. 给你一个最多可称8块石头的设备,可以知道总重量,32块重量不一样的石头,如何找到最重的三块石头(没时间思考了,随便说了下就结束面试了

五面整体感觉就是考察我这个人聪不聪明,问一堆智力题


五面完之后就陷入了漫长的等待,期间有联系内推人,问hr说我的面试评价不一致,还需要再讨论,感觉就是进入备胎池了


今天9.7收到意向书啦,特来牛客写下这篇面经,本来我本来想好两个标题,一个是现在这个,另一个是『字节跳动五轮技术面凉经』hhh,希望大家都有好offer


#校招##C++工程师##面经#
全部评论
大佬,请问你五面完之后等了多久收到意向书呀?我是三面完说等审批,都一个星期了
1 回复
分享
发布于 2020-09-07 20:10
ssp了
1 回复
分享
发布于 2020-09-07 20:43
饿了么
校招火热招聘中
官网直投
ssp!
1 回复
分享
发布于 2020-09-07 21:13
这些问题我怀疑自己在这个世界凑数了0.0
1 回复
分享
发布于 2020-09-08 16:52
太强了 感觉不在一个世界
1 回复
分享
发布于 2020-09-08 20:41
我去 看了你的面经准备放弃了 没几道会的
1 回复
分享
发布于 2020-09-08 23:24
老哥至少是个sp吧?
1 回复
分享
发布于 2021-01-01 13:29
大佬
点赞 回复
分享
发布于 2020-09-07 19:49
大佬,Raft、Paxos是简历上写了吗?怎么老是问分布式算法?
点赞 回复
分享
发布于 2020-09-07 19:55
sp警告
点赞 回复
分享
发布于 2020-09-07 20:23
真大佬,这面试难度和知识面真的和一般人不一样😂
点赞 回复
分享
发布于 2020-09-07 20:57
你为啥啥都会啊
点赞 回复
分享
发布于 2020-09-07 21:51
真的强
点赞 回复
分享
发布于 2020-09-07 22:24
ssssssp
点赞 回复
分享
发布于 2020-09-07 22:36
优秀的候选人哇hh还加了交叉面👀恭喜!!!
点赞 回复
分享
发布于 2020-09-08 00:28
是时候收山了,留点活路给我们
点赞 回复
分享
发布于 2020-09-08 01:09
实在是太强了,只能ssp了
点赞 回复
分享
发布于 2020-09-08 03:50
果然大佬,太强了
点赞 回复
分享
发布于 2020-09-08 10:18
 #java开发实习# 我也收到offer了 冰川啤酒 [拥抱]
点赞 回复
分享
发布于 2020-09-08 10:51

相关推荐

76 352 评论
分享
牛客网
牛客企业服务