字节全栈工程师面试外企面经,想去外企的小伙伴看过来

1,749 阅读22分钟

写在前面

本人是已经有三年经验的前端(其中两年在字节),因为一直想做全栈,所以申请转岗到服务端(也是在字节),但是时间不到一年半,因此服务端经验还很欠缺,这也导致我在面试一些公司的时候吃了亏,不过面试永远没有完全准备好的时候,只能在自己现有的阶段尽可能找到一个最优解吧。

因为外企一般面试轮数比较多,时间还是挺长的,大概是从 2 月中旬开始面第一家,到 3 月中旬确定最后的 offer 并且拒绝了其他 offer 结束。

由于这次是我第一次面试外企,踩了很多坑,总结了以下经验:

  1. 刷题!刷题!刷题!这是外企最基本的要求,即使你八股文背的不好,但是你题做的好,也能让你有更大可能通过
  2. 准备自己的亮点。这是需要在日常工作中或者业余时间中就准备的,比如我之前写的开源项目 github.com/YYCoder/pro…github.com/YYCoder/thr… 就为我带来了不少加分,在 Grab、AccelByte、Zuora、Zoom 的面试中都问到了这两个项目
  3. 八股文+系统设计一样不能少,这两者是相辅相成的。把八股文理解了,在做系统设计时可以更从容,常见的系统设计问题掌握熟练了后,可以加深对各个中间件的理解以及实际应用

接下来就是各个公司的面试问题总结。

AccelByte(全栈)

已发 offer,但是由于薪资比我现在低,并且公司是 21 年刚成立,福利制度还很不健全,所以还是拒绝了。

一面(前端)

没问算法,只问了项目和少量八股文,感觉面试官很着急,一共就不到 40 分钟就面完了

  • css BFC 了解么
  • css 伪类选择器的优先级
  • React 的事件系统
  • React HOC 了解过么
  • React 性能优化(如何保证组件不被重复渲染)
  • React 组件库有封装过么
  • React 数据管理方案,redux、mobx 有什么区别,适用于哪些场景
  • 前端模块化方案:amd、cmd、esm 都有什么区别
  • Webpack 或者 Vite 有了解么
  • Webpack 插件写过么
  • 如何迁移项目(如何偿还技术债)
  • 项目管理如何做
  • IM 项目的架构设计
  • 有做过什么性能优化

二面(服务端)

整整面了两个小时,没有算法,但问了很多八股文,涉及到 golang、代码规范、设计模式、数据库、缓存、消息队列。。。

  • channel 原理
  • slice 和 array 的区别
  • make 和 new 的区别
  • 除了 new 以外,还能怎么初始化结构体
  • golang 怎么实现继承
  • 对设计模式了解么,用过哪些设计模式
  • 用 golang 实现过哪些设计模式
  • sync 有了解过哪些
  • 消息队列了解吗
  • 消息队列的消息如何做去重
  • 对缓存有什么了解
  • mysql 的事务有了解么
  • redis 的数据结构了解多少
  • 什么情况下需要用到分布式锁

领英(前端)

一面挂。。。

一面

  • 热身题:给你一个很长的字符串,需要你按单词维度实现分页,每页是一个固定字符个数 count,要保证同一个单词不会在分页时被切分开

    • 其实很简单,只需要先 split 一下,然后遍历每个被split的单词即可,过程中统计字符个数,若超过 count,则不加入当前页
    • 由于是第一次面试外企,对流程还不熟悉,也不太会跟面试官沟通,结果热身题用了过于复杂的思路(一个一个字符去扫描😓),结果第一题浪费了太多时间
  • 算法题:给定一个 target,和一个旋转过的升序数组,在数组中查找第一个比 target 大的元素

    • 这道题是一道经典二分查找问题,可以先把数组拆分成两种情况,存在旋转点和不存在旋转点,如果不存在旋转点,则可以直接按正常的二分查找去找 target 即可,如果存在旋转点,则要向 target 的方向去搜索,让 mid 和 target 位于旋转点的同一侧
    • 当时由于第一题浪费了太多时间,结果第二题已经没剩多少时间了,所以最终也没做出来,就挂了
  • 前端页面之间的通信方式

Zuora(前端)

已发 offer,但由于我想做全栈,这个岗位不太符合我的要求,最后拒绝了。但是,无论是薪资、福利、假期都是很爽的,而且还能支持永久异地办公,非常人性,强烈推荐希望 work life balance 的小伙伴去试试他们家,他们家也不止有前端岗位,服务端也有,有意向的小伙伴可以脉脉上搜一下。

一面

  • 使用 dom 原生 api 根据一串 json(描述 vDOM 的节点)将真实的 dom 渲染出来

    • 允许 google 查 api。但是由于刚开始太紧张,以为要用 React,所以查了半天 React API,结果发现他们的 codesandbox 不支持用 React,就又改成用原生 DOM API,浪费了一点时间
  • 给你一个函数返回 promise,以及多个入参,让你保证按入参的顺序返回每个入参的结果

    • 很简单的一道 promise 问题

二面

设计一个组件可拖拽的数据看板页面

这道题非常模糊,其实是在过程中一直在和面试官聊,聊的过程中不断提出问题,然后想办法解决。主要考察的是前端组件设计、数据存储设计这方面。

三面(Hiring Manager)

基本上聊得都是有的没的,没有涉及技术细节

  • 让我展示一下我之前的工作成果(我说我之前主要做的是后台项目,不太方便展示,就只展示了一下我的开源项目)
  • 聊了聊个人的优势、劣势
  • 聊了聊做过有挑战的项目

Jerry.ai(全栈)

二面挂,主要在于跟他们招聘的岗位不匹配,他们要求是高级服务端开发,而我服务端经验还不足。

一面(Coding)

  • 给一个 [10, 2] 这样的数组,让他拼接成一个最大的数值

    • 首先需要考虑到最大的数值可能会超过 js 最大安全整数,因此要返回字符串
    • 最简单的做法,需要将每个元素转成字符串,然后依次比较,把最大的字符串放在首位依次拼接即可(这里考察到了 js 的字符串比较 api,js 是会一次比较每一位的编码,因此 ‘2’ > ‘11’ 就是 true)
  • 经典的 dfs+回溯问题,给一个字符串,返回对应的 ip 地址(leetcode 94)

二面(System Design)

设计一个分布式 LRU 缓存。

  • 分布式一致性哈希

  • 根据哈希函数计算节点位置如何保证分布均匀

    • 分布式哈希+虚拟节点
  • 分布式缓存节点如何扩容

    • 如何做数据迁移?主要为了避免迁移过程中更新了某个 key 到新节点,然后从旧节点将数据迁移过去时覆盖了

      • 根据数据的时间戳判断,可以对每个 key 再保存一个时间戳,迁移到新节点时,如果发现时间戳是比新节点上的 key 要旧的,就抛弃即可
  • redis 主备之间如何同步

  • redis 从节点挂了重启时如何保证数据恢复

  • 主从节点选举方式

Grab(服务端)

已发 offer,最后由于薪资和岗位的缘故拒绝了。整体面试体验还是非常好的,面试官会在你遇到困难时主动给你提示,并且会基于你熟悉的地方深挖,比如问我的开源项目比较多。

一面

  • 最长递增子数组,返回 len

    • 直接遍历即可,都不用双指针
  • 最长无重复子串,返回 len

    • 经典滑动窗口
  • 合并区间

    • 没啥特殊算法思想,去 leetcode 做一遍就会了
  • 前三道题很快就做出来了,后面突然感觉没啥聊的了,就和面试官聊了聊我的开源项目

二面

  • 算法题:合并两个有序链表(白板 coding 但面试官没有扣细节,主要讲了下实现思路,写了写伪代码)
  • 实现一个限流器,写伪代码(没写上来,但说了一下用 redis 的实现思路,固定区间的方案)
  • 了解数据库 client 的实现原理么(不会,只提到了链接池)
  • golang 的 GC 原理(不会)
  • 数据库索引了解么(B+树结构)
  • 缓存和数据库一致性如何解决(只讲到了只读缓存的删除策略)
  • 了解分布式理论 CAP 么(不了解)
  • 消息队列了解吗,如何做去重(说了下自己项目中怎么做的)
  • 分布式事务(不了解)
  • 讲了讲我的开源项目(讲了一堆)

三面(Hiring Manager)

面试官比较忙,因为开会迟到了一会。

  • 英文自我介绍
  • 聊项目
  • 设计一个 Role-Based 权限控制系统(一开始没 get 对问题,说了一大堆 SSO、OAuth 的东西,因为面试官提到了 Authorization,最后理解了以后时间关系也没有展开太多)
  • 算法题:BST 中找到第 k 大的元素(直接中序遍历)
  • 说说自己的优势、劣势
  • 说说之前做过最有挑战的项目
  • 聊了聊期望薪资

Tubi(前端)

总体感觉 tubi 的面试都比较实际,没有考任何 leetcode,都是结合实际场景出发的问题,难度都不大,只要是做过前端肯定都遇到过的场景。要求你用 js react 实现特定需求,然后不断优化代码,并且过程中是完全可以 google 的,这一点感觉很人性。

最后由于已经确定了其他家 offer,就没有继续面六面。

一面

  • 给你个 url,让你从这个 url 中获取所有的数据,并根据传入的 schema 来过滤需要的数据

    • 其实就是用 fetch 调接口,然后然后根据 schema 生成一下 RegExp 来过滤数据,再配合一些数组常用的 method,比如 slice、filter、map、reduce 这些即可
    • 写完后面试官问了很多代码可以优化的地方,以及对缓存的理解等等

二面

二面是一个法国小哥,英文发音很标准,刚开始先让自我介绍一下,然后又让我介绍一下之前呆过的公司,做过的项目,磕磕巴巴都答上来了。

由于是本人第一次和歪果仁面试,所以非常紧张,火急火燎地在前一天晚上用英语准备好了各种可能的问题,结果就用上了自我介绍,不过面试过程中发现交流起来还好,我说的基本对方都能听懂,反而是三面的印度老哥的口音让我经常听不懂,还需要他打字我才明白😂。

  • 要你实现一个虚拟键盘,需要支持按键盘的上下左右键移动键盘上的标记元素,并且支持按下回车时选中当前元素,并展示出来

    • 用到了 React 相关的东西,问题也很基础,当时由于太久没写 js,switch-case 居然忘了需要加 break,可能是因为 golang 写的时间久了,搞混了。这个问题卡了好久,气的想锤自己。。。不过最后还好发现了,算是完成了整个问题

三面

三面听口音像是个印度老哥,看起来比较资深,感觉主要难点在于经常听不懂他的发音,需要他打字才能理解。

  • 给你一个 mock-url,通过该 url 去拉取数据。然后让你实现一个 input 框,根据输入内容去向 mock-url 拉取数据,并将内容展示出来

    • 也是用 React,并且优化时提出了用 debounce,然后自己实现了一波,最后还聊了一下缓存相关的知识,比如 LRU 的实现原理

四面

四面是中国人,前端 leader,人也在美国,所以有时差,又是早上一大早起来面试😭。

  • 聊了比较长时间项目,前端、后端项目都问到了,并且聊了聊感觉比较有挑战的事情

  • 实现一个「原地」数组深度扁平化方法

    • 因为很久没有准备前端面试题了,一上来居然没想到思路,卡了比较久,最后只实现了非原地的方法,并且面试官希望去掉递归,也没想到怎么实现,感觉这一面表现不太好

五面

五面是技术 VP,也是中国人,只有半小时,主要就聊项目了。

  • 问我的开源项目的原理
  • 聊之前做过有挑战的项目,前端和服务端的都聊了一遍

Zoom(服务端)

已经谈了 offer,由于薪资实在太低,相比我现在要降薪 25%,所以拒绝了。前三面面试体验还不错,就是最后一面 Hiring Manager 迟到了时间比较长有点不太专业。

一面

  • 一道语言基础题,考点:

    • struct 内存对齐
    • for-range 迭代变量拷贝(若改成指针即符合预期)
type Foo struct {
	int64
	n int32
}
s := make([]int, 3)
s[0] = Foo{n: 1}
s[1] = Foo{n: 2}
s[2] = Foo{n: 3}

for _, e := range s {
	e.n++
}

// 根据第一个输出,推断出后面的输出
for i:=0; i<len(s); i++ {
	fmt.Printf("%v s[%d] = %d", &s[i], i, s[i])
}
  • 用 go 语言实现一个 k-v 内存缓存,按优先级满足如下要求:

    1. 线程安全,满足读读高并发
    2. 如何不加锁实现(GMP 模型)
    3. 读写高并发
  • 算法题,经典问题,无序数组中找到第 k 大的元素

    • 维护一个大小为 k 最小堆,不断向堆中添加,元素,并把顶部元素踢出,最后剩下的顶部元素就是第 k 大的元素
  • sync.Pool 了解过么,底层原理知道么?

  • GMP 模型

  • 有用过 pprof 吗?

二面

没有聊技术,就总结了一下项目,然后给我介绍了 zoom 的情况,并且还问了下期望的薪资。

我也很奇怪,因为二面一般还需要面技术的,但是这个主管基本上没有和我聊任何技术。

三面(HR)

主要聊了聊过去的项目,之前的公司,以及想不想去苏州,还有薪资情况等等。

四面(Hiring Manager)

面试官迟到了快 20 分钟,这确实让我感觉有点不专业,来了以后说之前在开会,并且他紧接着还有另一个面试,所以留给我的时间只有 40 分钟。

  • 聊项目

  • 聊了为什么转服务端

  • 聊了前端和服务端的区别

  • 问了下一面的时候问的算法题

  • 算法题:实现一个栈,支持 push、pop,以及 getMax 方法,要保证这三个方法都是 O(1) 的复杂度(只说思路,不用 coding)

    • 答上来了,利用单调栈即可,跟 leetcode 一道原题类似,只不过那道题是 getMin

亚马逊(服务端)

笔试劝退。。。

笔试

如下第一道是 demo 的练习题,后面两道是真实的笔试题,由于是直接从网页上 copy 下来的,不太易读,将就着看吧😂。

Amazon Fresh Promo (example question)

Amazon Fresh is running a promotion in which customers receive prizes for purchasing a secret combination of fruits. 
The combination will change each day, and the team running the promotion wants to use a code list to make it easy to change the combination.
The code list contains groups of fruits. Both the order of the groups within the code list and the order of the fruits within the groups matter.
However, between the groups of fruits, any number, and type of fruit is allowable.
The term “anything” is used to allow for any type of fruit to appear in that location within the group.

Consider the following secret code list: [[apple, apple], [banana, anything, banana]]

Based on the above secret code list, a customer who made either of the following purchases would win the prize:
orange, apple, apple, banana, orange, banana
apple, apple, orange, orange, banana, apple, banana, banana

Write an algorithm to output 1 if the customer is a winner else output 0

Input
The input to the function/method consists of two arguments:

codeList, a string array of space-separated values representing the order and grouping of specific fruits that must be purchased in order to win the prize for the day.
shoppingCart, a list representing the order in which a customer purchases fruit.

Output
Return an integer 1 if the customer is a winner else return 0.

Note
‘anything’ in the codeList represents that any fruit can be ordered in place of ‘anything’ in the group.
‘anything’ has to be something, it cannot be “nothing.”
‘anything’ must represent one and only one fruit.
If secret code list is empty then it is assumed that the customer is a winner.

Examples

Example 1:

Input:
codeList =
[[apple, apple],
[banana, anything, banana]]
shoppingCart =
[orange, apple, apple, banana, orange, banana]

Output:
1

Explanation:
codeList contains two groups - [apple, apple] and [banana, anything, banana].
The second group contains ‘anything’ so any fruit can be ordered in place of ‘anything’ in the shoppingCart.
The customer is a winner as the customer has added fruits in the order of fruits in the groups and the order of groups in the codeList is also maintained in the shoppingCart.

Example 2:
Input:
codeList =
[[apple, apple],
[banana, anything, banana]]
shoppingCart =
[banana, orange, banana, apple, apple]

Output:
0

Explanation:
The customer is not a winner as the customer has added the fruits in order of groups but group [banana, orange, banana] is not following the group [apple, apple] in the codeList.

Example3:
Input:
codeList =
[[apple, apple],
[banana, anything, banana]]
shoppingCart=
[apple, banana, apple, banana, orange, banana]

Output:
0

Explanation:
The customer is not a winner as the customer has added the fruits in an order which is not following the order of fruit names in the first group.

Example4:
Input:
codeList =
[[apple, apple],
[apple, apple, banana]]
shoppingCart=
[apple, apple, apple, banana]

Output:
0

Explanation:
The customer is not a winner as the first 2 fruits form group 1, all three fruits would form group 2, but can't because it would contain all fruits of group 1.
To increase efficiency, the Amazon shipping team will group packages being shipped according to weight.
They will merge a lighter package with a heavier package, which eliminates the need for separate shipments.

More formally, consider n packages, where packageWeights[i] represents the weight of the ith package.
You can combine the ith and (i+1)th package if packageWeights[i] &lt; packageWeights[i+1], then discard the ith package.
After this operation, the number of packages is reduced by 1 and the weight of the (i+1)th package increases by packageWeights[I].
You can merge the packages any number of times.

Find the maximum possible weight of a package that can be achieved after any sequence of merge-operations.

Example

For example, packages are described as package_weights = [2, 9, 10, 3, 7].

The optimal order of operations is, using 1-based indexing:

Combine the packages atindex 2 and index 3, the new array ofpackage weights becomes [2, 19, 3, 7].
Combine the packagesat index 1 andindex 2, the new array ofpackage weights becomes [21, 3, 7].
Combine the packages at index 2 and index 3, the new array of package weights becomes [21, 10].

We can not combine the packages anymore.

The weight of the heaviest package achievable after merging is 21.

Function Description

Complete the function getHeaviestPackage in the editor below. 

getHeaviestPackage has the following parameter:

int packageWeights[n]:the weights of the packages

Returns

long_int: the weight of the heaviest package after merging all possible packages.

Constraints

1 ≤n≤2·105
1 ≤ packageWeights[i]≤ 109

Input Format For Custom Testing

The first line contains an integer, n, the size of packageWeights.

The ith line of the n subsequent lines contains a single integer that represents the weight of the ith package, packageWeights[i].

Sample Case 0

Sample Input For Custom Testing

STDIN FUNCTION 
-------------
4→packageWeights[] size n = 4 
20→packageWeights[] = [20, 13, 8, 9] 
13
8
9

Sample Output

50

Explanation

The optimum series of merges is:

Combine packagesat index 3 and index 4, the new array of package weightsbecomes [20, 13, 17].
Combine packagesatindex 2 and index 3, the newarray of package weights becomes [20, 30].
Combine packagesat index 1 andindex 2,the newarray ofpackage weights becomes [50].

Sample Case 1

Sample Input For Custom Testing

STDIN FUNCTION
-------------
4→packageWeights[] size n = 4 
30→packageWeights[] = [30, 15, 5, 9] 
15
5
9

Sample Output

30

Explanation

Here, we can merge the last 2 packages to have [30, 15, 14]. No further merge operations are possible.
Amazon Web Services (AWS) has several data centers which have multiple processors that perform computations.
In one such data center, these processors are placed in a sequence with their IDs denoted by 1, 2, .., n.
Each processor consumes a certain amount of power to boot up, denoted by bootingPower[i].
After booting, a processor uses processingPower[i] of power to run the processes. For maximum utilization, the data center wishes to group these processors into clusters.
Clusters can only be formed of processors located adjacent to each other. For example, processors 2, 3, 4, 5 can form a cluster, but 1, 3, 4 cannot.

The net power consumption of a cluster of k processors (i, i + 1, .., i + k - 1) is defined as:

<img src="<https://hrcdn.net/s3_pub/istreet-assets/FJ3wqOpTONY1iDlxbfkt9g/D56%20(4).png>">

That is, net power consumption = maximum booting power among the k processors + (sum of processing power of processors) * k.

A cluster of processors is said to be sustainable if its net power consumption does not exceed a given threshold value powerMax. 

Given the booting power consumption and the processing power consumption of n processors denoted by bootingPower and processingPower respectively,
and the threshold value powerMax, find the maximum possible number of processors which can be grouped together to form a sustainable cluster.
If no such clusters can be formed, return 0.

Note: It is not mandatoryfor all clusters of size k to be sustainable.Even onesuch cluster is sufficient.

Example

bootingPower = [3, 6, 1, 3, 4]

processingPower = [2, 1, 3, 4, 5]

powerMax = 25

If k = 2, any adjacent pair can be chosen. The highest usage is the pair [4, 5]with net power consumption 4 + (4 + 5) * 2 = 22. Next, try k = 3. Group the first 3 processors together as:

<img height="281" src="<https://hrcdn.net/s3_pub/istreet-assets/H2XusqE_8yBrmoU5QC81xw/D56%20(6).png>" width="536">

Here,

Maximum booting power = max(3, 6, 1) = 6
Sum of processing powers = 2 + 1 + 3 = 6
Thus, net power consumption = 6 + 6 * 3 = 24 &lt;= powerMax

Thus, we can group k = 3 processors to form a sustainable cluster.
Note that the minimum power consumption to form a cluster of k = 4 processors is 46, by forming a cluster of the first 4 processors.
Since this cost is greater than the threshold, we cannot form a cluster with 4 processors.
The maximum possible cluster size is 3.

Function Description

Complete the function findMaximumSustainableClusterSize in the editor below.

findMaximumSustainableClusterSize has the following parameters:

int processingPower[n]:the power consumption of each processor in running the processes

int bootingPower[n]:the power consumption of each processor in bootup

long_int powerMax:the threshold power consumption

Returns

int: the maximum cluster size which is sustainable, if no cluster exists, return 0.

Constraints

1 ≤ n ≤ 10 5
	
1 ≤ powerMax≤ 10 14
	
1≤ processingPower[i]≤ 10 4
	
1 ≤ bootingPower[i]≤ 10 9
	
length of processingPower= length of bootingPower

Input Format For Custom Testing

The first line contains an integer, n, the number of elements in processingPower.

Each line i of the n subsequent lines (where 0 ≤ i &lt; n) contains an integer, processingPower[i].

The next line contains an integer, n, the number of elements in bootingPower.

Each line i of the n subsequent lines (where 0 ≤ i &lt; n) contains an integer, bootingPower[i].

The next line contains a long_integer, powerMax.

Sample Case 0

Sample Input For Custom Testing

STDIN FUNCTION
----- --------
5→processingPower[] size n = 5
4→processingPower = [4, 1, 4, 5, 3] 
1
4
5
3
5→bootingPower[] size n = 5
8→bootingPower = [8, 8, 10, 9, 12]
8
10
9
12
33 →powerMax = 33

Sample Output

2

Explanation

Here processingPower = [4, 1, 4, 5, 3], bootingPower = [8, 8, 10, 9, 12] and powerMax = 33.

We can form a cluster of size k = 2, consisting of the first 2 processors.
The net power consumption is net power consumption = max(8, 8) + (4 + 1) * 2 = 18, which is less than the threshold.
There are other clusters of size 2 which can be formed as well. However, the minimum net power consumption for a cluster of size 3 is 37 (the first 3 processors, max(8, 8, 10) + (4 + 1 + 4) * 3 = 37).
This is greater than the threshold (33), thus not sustainable. The maximum possible sustainable cluster size is 2.

Sample Case 1

Sample Input For Custom Testing

STDIN FUNCTION
----- --------
3→processingPower[] size n = 3
10→processingPower = [10, 8, 7]
8
7
3→bootingPower[] size n = 3
11→bootingPower = [11, 12, 19]
12
19
6→powerMax = 6

Sample Output
0

Explanation

It is not possible to form any sustainable cluster for the given processors with net power consumption less than or equal to powerMax, thus the answer is 0.

FreeWheel(全栈)

已发 offer。分两轮,第一轮电话,第二轮连续 4 面。

一面(电话)

基本上只问了前端的问题,因为前端项目这块讲的时间太长了。

  • 介绍项目(讲了快半小时,过程中一直在回答面试官的疑问)
  • react hooks 使用上有什么需要注意的地方(比如不能用在 if-else 里面)
  • 为什么选择用 mobx?
  • mobx 和 redux 有什么区别?

二面(现场)

连续 4 面都是在现场,一下午面完。

二面问的前端相关的东西比较多,没有问算法题。

  • React 有哪些常用的 hook
  • React hook 有哪些使用的注意事项
  • 为什么选择 mobx
  • 为什么转服务端
  • 项目相关的问题,比如架构设计、存储设计等等
  • 使用 typescript 有什么感想,优势是什么、劣势是什么

三面

时间有点久,其他问题想不起来了。

  • 算法题:两个相交链表的交点(leetcode 原题,很简单)

  • 问了一个 solar 相关的问题,是他们工作中实际遇到的问题,大概是:solar 在搜索时可以通过 pageSize&pageOffset 来分页查询,但是一旦 pageSize 非常大,会将所有数据 load 到内存中,导致内存飙升,有什么好的解决办法?

    • 因为我完全没有了解过 solar,所以这道题基本上都是结合自己的一些经验和想法答的,最后面试官看我 get 不到也没有继续问了

四面

其他问题也想不起来了,没有印象深刻的,基本都是常见八股文

  • 英文自我介绍
  • 为什么转服务端,用英文回答
  • 算法题:类似 leetcode 原题「压缩字符串」,但是比它要简单,输入是字符串,并且返回结果也是字符串,用双指针就可以了
  • golang 中 struct{} 的使用场景
  • golang 的闭包有了解么
  • 为什么 rpc 序列化协议选择 thrift 而不是 protobuf

五面

基本上聊的就比较杂,更多是个人发展规划这种比较虚的东西。

  • 英文自我介绍
  • 为什么转服务端
  • 为什么想跳槽
  • 做过哪些 sql 优化
  • 为什么 rpc 序列化协议选择 thrift 而不是 protobuf
  • 未来有什么规划

微软(服务端)

一面挂。。。

一面

  • 聊项目半小时

  • 算法题:实现一个大数相减的方法,比如 a = ‘123456’,b = ‘123’,a-b = ‘123333’,并且要支持负数,比如 b = ‘12’ a = ‘1’,a-b = ‘-11’

    • 题其实不算难,但是细节比较多,做出来了但是 bug 有点多,还是蛮可惜的

结语

最后想说的是,跳槽的关键在于前期准备,面试只是验证成果的时候。准备的过程非常辛苦,包括心理上和身体上的。比如,每天工作了一整天,已经腰酸背痛,但是下班到家后,你还需要坚持刷题、背八股文,复习到十一二点是常态;由于是准备面试外企,还要用额外的时间练习英语;对好胜心比较强的同学,看着同事们做出了很多工作上的产出,自己更要抑制住这种好胜心,因为你的目标不在这里等等,其中的辛酸只有自己知道。

准备的过程固然孤独且辛苦,但是所有努力终究会有回报。也祝所有想过上 work life balance 生活的小伙伴都能早日拿到理想的 offer。