新手奶爸2个月在职高压刷题+找到工作,分享些经验

avatar 440493
xtxsinan
19284
53
先说下背景,我也算是转码的,博士读的是交通工程,19年毕业后进入一家中资自动驾驶公司做data engineer,过去的三年虽然很忙很累,但也见证了公司和自己的快速成长。

我跟一般转码不太一样的是,我本科就是SE,而且高中还搞信息奥赛,coding对我倒不难,但博士毕业时已经很多年不在cs领域,对工业界最新的技术和工程实践都极为不熟悉,刚工作的时候经常要拿很多小白问题请教senior的同事。但因为所在的组快速扩张,入职时的manager已经变成我的manager的manager的manager,当时的十几人的组现在已经100人;项目也一直很多,也快速得到了锻炼。刚入职没多久就开始own一些比较重要的service,第二年就开始独立开发新项目,第三年就已经开始lead一些项目——虽然合作的同事级别都更高,到去年年底自认已经是一个比较合格的senior engineer(title也是,但薪水比一线大厂同级别有差距),而且对自动驾驶大数据相关领域也有比较广的了解。

今年春节后,因为多种原因,下定决心跳槽,于是休了一个5周的产假(在中资公司对男员工这个长度基本已经是极限,虽然公司并没有任何补助,完全靠加州政府的补贴)。因为平常工作很忙,而且还有一个刚出生没多久的小孩,休假前完全没时间准备,从产假开始的时候才开始准备,一边准备也就一边开始约面试,第二个月则是一边上班一边找借口面试,一边也还在继续准备。

因为在现公司工作比较忙,压力也不小。同时还因为有了新出生的小孩,虽然我母亲在这里帮忙,但因为老婆产假已休完,也还得负责一些家务,同时因为新增了人口,目前的2b不够住也在买房,自己感觉可能是自己活到现在最忙最紧张的一段时间。好在家人一直给予了很多支持,自己也很努力,最后拿到了几家自动驾驶公司的offer,从中选择了自己一直的dream company waymo,总包涨了50%左右,超出了自己一开始设定的目标。

不过虽然最后结果不错,但这次因为准备时间很短,题还没刷熟就直接上战场了,系统设计、OOD这些短板也比较多,前半段面试过程受挫挺多,第一轮技术面不过的超过一半(VO因为都在后半反而过的比较多),也总结了很多经验教训。个人觉得其实具体的面经除非真的是小公司否则真的撞上的可能性非常小,但关于如何对各种类型的面试做准备、和分配准备的时间,如何规划时间和调节心态,其实是更有价值的经验,这里就跟各位分享一下,希望对地里其他同学有所帮助。

1. 关于面试题的准备和实战经验:

面试有几种基本类型。
最常见的是算法题,因为占据面试一半以上而且常常起决定性作用,即使对自己coding再自信,肯定要准备。
其他的coding类还有OOD和SQL,OOD的话Amazon系的公司考的比较多,我因为是data职位又是用python,OOD确实不太重要,除了Amazon和zoox要考以外,就没碰到过,后半段我基本上没花太多精力;SQL面试整体可能很少见,但data engineer还是相对比较常见,有碰到3、4家要考,我个人觉得data engineer还是肯定要准备的,而且实际日常工作也经常用,准备也有好处。
非coding的最重要的就是系统设计了,因为我也算转码,而且本科学软工是挺久以前,对工业界各种cloud base的系统的了解其实主要限于自己公司技术栈里有的东西,而自动驾驶公司因为交付的产品是offline的,online服务很少,我们作为av infra也根本不涉及终端用户,所以技术栈其实跟一般互联网公司是不太一样的,我是花了比较多时间补足这块的。此外behavior和项目经验什么的,我因为项目经验多,倒没怎么准备。



1.1 算法题

1.1.1 在职跳槽,刷题时间有限,基本上也就能刷个几十道或最多一百多道,就不要指望自己能够靠刷题够多来面试碰到遇到的题。还是应该分类做,对于常见的算法类型,集中做一批题,在做题的过程去中熟悉三个东西:1. 这个算法的原理;2. 这个算法适用的题目的类型;3. 这个算法的实现。对于自己比较熟悉的类型可以少做些。但任何类型都应该做个几道,保证自己面试中能很快写出来。

1.1.2 不要浪费时间在太偏门的类型上。
比如虽然我自己后来花了时间学会了BIT(binary indexed tree),但我认为任何公司都不应该出这个题来考,因为这个算法除非有白板辅助画图,否则15分钟都很难给人讲明白,实际上我也碰到面试中有题目可以用BIT做,但面试官根本不知道BIT是啥,最后也就没用。其他的union find,segment tree merge sort这些稍微大众些的,其实考到几率也很低。绝大部分面试还是常规的几种,bfs,dfs, 树,recursion,two pointer二分查找,dp,heap,排列组合,dijkstra,这些吃透了 90%的公司可以应对全部的coding轮

1.1.3 冷门类型有一个例外,monotonic stack。其实对一些喜欢出难一些的题的公司,相对有比较大概率能考到。很多针对数组的题其实这个都是一种可以用的思路,如果感觉要算一种看起来像n2但考官期待on的题,有不小可能可以用这个。
另外a star作为dijkstra的一种常见优化,可以看一下。

1.1.4 有一些可以大大减少写code量的该语言的trick建议系统练习下,比如python里的bisect,combinations, sorted+lambda,setdefualt,enumerate,zip。

1.1.5 如果对dp苦手,可以先用暴力recursion的方式做,然后慢慢写出迭代公式来,再加个lru_cache就可以对state有记忆,时间复杂度是一样的,也可以认为是dp解法。

1.1.6 所有的coding面试也是一种小规模系统设计面试。
开始写之前,应该先确认题目要求(需求),然后有成熟的思路(用什么算法),和实现方案的设计(比如一些重复操作写成function),并可以提前估计一下时间复杂度,并问一下考官觉得这个复杂度够不够好(不会有人觉得这么问减分的),各种edge case或invalid的case在不在scope内。这个过程看似费时,其实可以节省大量时间,防止自己在错误的方向上花费太多时间,或者花精力做不必要的error handling,重复的代码写成function也方便之后题目要求变更的时候代码复用,和debug的时候修改。

1.1.7 写完code以后可以先问一下考官要不要先讲一下思路。
一来,有时候可能因为你写的太快、或者解法不常规、或者变量名不够详细,或者单纯是考官不那么sharp,写代码的时候考官可能会没跟上你的死路,这时候测试之前先跟他讲明白思路,有利于他尽快意识到算法是可行的,而不会在测试出问题的时候建议你用其他解法。第二,也有考官会觉得你先理顺思路再执行代码是一种做事稳妥的好习惯。最后,如果这时候一边讲一边发现了自己code的问题,会比之后运行发现问题显得更好也更从容,而且也节省了debug的时间。

1.1.8 有一些跟算法强相关的技术,比如rate limiter,几种不同的cache机制,geo data (quad tree),文本搜索提示(trie),如果自己面试的领域在用(比如网页的backend 肯定有rate limitet概念;数据访问频率不匀就肯定要用cache解决hot spot),在某个面试里以coding或系统设计的形式被考到几乎是一定的。建议准备一下。

1.2 系统设计准备

1.2.1 每次system design面试实战其实自己都很有收获,有时能考官会直接告诉你一些技术盲点,最起码也能意识到自己哪里的知识不足。如果时间充裕,像地里推荐的一样系统的上玩educative的课,并看完amzn.to这本书,再找人mock几次,当然准备最充分。但如果像我一样在职跳槽,时间有限,system design其实挺适合在游泳中学会游泳的,当然前提是你的coding已经准备的比较充分,能够保证自己进VO可以考到system design,同时也有比较多的不想去的公司能进面试可以用来练手。

1.2.2 educative的课学一下还是有用的,能系统梳理一下知识,补足盲点,但过度依靠这个课的问题是,这里面很多例题花了大量篇幅在讲一个小细节怎么解决上,对于课程来说,这样可能可以深入讲一些知识点,帮助应对一些follow up questions,但太依靠educative的解题套路,容易在实际面试中不能先抓住重点,把大框架列出来。建议还是要多学习网上别人针对真实面试题画的uml设计图,或者是各大公司技术blog里的一些uml,让自己习惯拿到一个题先写出最重要的几个模块,然后逐步细化,实战中是坚决不要按educative的资料里一个个模块细致讲过去的。换句话说,要bfs,不要dfs。

1.2.3 个人认为,最好的系统设计的学习资源,其实是自己公司各个项目的设计文档。
对在职跳槽,建议优先吃透自己公司自己组的项目设计文档,这些项目其实每一个都可以看成是一个系统设计题,如果是跳槽到相近领域,那么涉及的问题其实跟新工作的问题也比较接近,而设计文档本身,除了UML设计图,还常常有一些对技术选型的分析,也往往会分析确实比较重要的方面的一些考虑,而不会浪费篇幅在很多不重要的细节的考虑上,一定是比任何网络课程和面经更好的系统设计题实战资料。在看项目文档的过程中,如果碰上不明白的还可以直接找同事且请教一下。吃透自己组的项目,退一万步万一自己跳槽没成功,对继续在现公司的工作也很有帮助。

1.2.4 如果自己lead过任何项目,对这些项目要以更高的标准吃透。
在整个面试的过程中你一定会被反复问到之前做过的项目的,不光是项目经验或者behavior论,系统设计轮甚至coding轮开始介绍项目经验的时候都可能被考官盘问。要对别人对你所有的技术选型和架构设计决策的所有可能challenge有充足的准备。
考官可以原谅你对自己不熟的领域了解不够深入,但一定不能原谅你对自己lead的项目了解不够深入。而且对自己lead的项目复盘一般也能更深入。
准备的时候,可以把这些项目当做系统设计题来复盘,看看当时的技术决策有没有任何不合适的地方,如果确实有设计的不合理又不好从外部因素解释的,建议重新仔细做个设计。这个重新设计的研究调查工作甚至你可以就作为给自己的一个一天半天的ticket来做。既然当时不是最优方案,refactor以后一定有明显的好处,那么为设计花的时间就是值得的,在manager那就应该能挂上号。即使manager觉得不需要马上实现这个改动,未来万一没跳槽成功有机会把实现也做了,也是自己考评上的一个加分项。可以说是既准备了面试,又进行了本职工作。

如果没lead过项目,又想找senior以上的职位,就把自己当做参与过的项目的lead,参照上面练习即可。

1.2.5 建议对自己的领域最常用的2-3个技术专门系统学习一下。
有一些面试可能会针对这些领域有一些trivia question,比如我就遇到了专门针对spark问了一系列trvia questions。
因为是领域常用技术,系统设计的考官也有较大概率会问到或涉及与之相关的问题,这些准备也能帮助你聊得比较深入。
甚至偶尔coding轮面试官也会聊到这个技术,如果能说一些技术点,也是加分项。

1.2.6 类似的,对自己最常用的coding语言也可以深入了解一下,比如看一遍xxx trivia questions。虽然大部分公司的面试不会有一个专门的trivia question模块,但还是偶尔会在系统设计或聊项目经验乃至跟hiring manager海聊时涉及。比如你如果用python但不知道python GIL导致非IO的CPU计算相当于伪多线程,肯定是丢分的。对自己主力语言得对它基本的编译、执行的一些特性有了解。

1.3 SQL面试

1.3.1 如果跟我一样是data engineer,肯定会有公司拿出一轮来面sql的,准备一下比较好
1.3.2 即使对sql再熟,也还是得在leetcode刷十几道题熟悉一下,特别是复杂些用法比如row number, explode等等。不过不太用准备写recursion cte这种。不太可能有公司会考到。毕竟sql一般也不用来干这个,有类似需要大家一般就写普通code了。
1.3.3 很多sql面试都只能用mysql,所以如果自己平常用其他sql,可以用leetcode实际做几道题熟悉下mysql的各种函数名,虽然考官基本都能允许你现查——如果你熟悉的是别的sql,但自己提前熟悉可以节省时间。
1.3.4 注意下自己有没有明显的知识盲区,比如我自己就是有次突然被考到写个insert,但一时想不起来咋写,因为自己平常对rdbms的操作只有select和update,虽然最后还是过了,但让考官有些疑虑。


1.4 OOD
1.4.1 考ood的公司比较少,因为我自己是写python的data engineer,所在领域其实没有太复杂的ood,面到的公司也只有一家考了ood。ood其实跟算法题很不一样,需要专门练习,对一般data engineer花很多时间不值得,还不如完全放弃。当然如果是一些用java的、业务逻辑经常要抽象成类、各类之间关系又比较复杂的组,考ood的可能性就比较大。可以提前上网看看自己会有面试的公司都有什么题型,如果OOD出现较多就准备,否则放弃。

1.4.2 虽然ood建议可以放弃准备,但强烈建议看一下ood的最经典例题——设计停车系统。这个题虽然最常见的是作为ood考到,但我自己是被当作系统设计题考到,考官还同时考了一下表怎么设计,几个业务的sql怎么写,等于也可以做为sql题;然后我还见到有公司把这个当coding题考(用双向hash table加快停车位检索)。感觉parking system就是一个非常经典的基本问题。建议从算法,sql,数据库表设计,系统设计,ood等全方面吃透。一方面可以用一道题为多个类型的面试做准备,而且可以通过全方位吃透达到一种融会贯通,对整体的能力也是有提高的。

2. 求职时间规划和心态调整

2.1 不要浪费时间在完全看不上的公司的recruiter call上,实际上跟recruiter聊也挺费时间的,而且很多也要block一个时间,虽然只有15分钟,但会影响你用大块的时间准备面试或做技术面试。

2.2 时间安排很重要。先安排不想去的公司(如果面试都不正规就没必要了)。大公司(全公司统一安排面试而不是各组自己安排面试的)流程要长一些,也不能安排太晚。最想去的几个公司尽量排在后段(可以通过每一步约时间尽量往后来控制),而且VO能凑在差不多的时间(方便直接一周pto全去了),这样到时经验最充足,且方便counter offer,也不会导致需要在理想的公司还没出结果的时候迫于期限reject offer。

2.3 自己闭门准备的再多,真正实战的压力还是很不一样。第一次coding和第一次system design我都做的很糟,跟紧张和不太适应有倒计时的环境有挺大关系。到后期等到有过1-2次正常发挥了基本就很淡定而且即使时间紧也不太在意时间了。

但这并不是说可以完全不准备就接面试,哪怕是不想去的公司。这样很容易表现过于糟糕,会打击自信。我自己一开始就很受挫。还是做个几十道有一定把握以后再开始约技术面比较好。

2.4 如果是感觉自己表现挺好但是被reject的,不用难受,实际上事实证明大部分面试的结果跟自己的感受是相符的。reject有可能是突然hire freeze(我就遇到了facebook明明面试题做的很顺,后来recruiter拖了一阵子说是不move forward因为找不到想要的manager,应该是hire freeze了);有可能是突然好几个candidate接受offer,坑已满;有可能是恰好有一个人表现的比你更出色或有更多domain expetience(小公司很常见);或者干脆就是面试官不够公正或自己水平不行(我就碰见过判断错时间复杂度的)。很多时候并不是你自己的问题,所以平常心对待被拒。focus在自己每次面试的表现的自我总结就好。

2.5 所有的技术面试其实同时都是behavior面试,在面试的过程中积极的与面试官沟通,积极的响应面试官的提示或思路纠偏,清晰有条理的表达自己的想法和思考,表现的友善合作和蔼可亲,都是能加分的

2.6 不管自己过去是否足够优秀,要坚信自己肯定能找到下家。
除去其他因素,很多时候面试不过当然也可能是自己水平确实不够,这时候也不要难过,有可能是这家公司要求的能力集跟你不够匹配。比如我最想去的公司就是waymo,而waymo的coding题虽然难,但重视思路多过细节实现,又往往以一个medium的题作为引子,之后逐步加难,我自己自认推理归纳能力比较强的,waymo的面试我反而做的比很多题没那么难的公司顺手。面试了十几家公司下来,自己的整体感觉是匹配是相互的,自己更想去更适合的公司,往往面试考察的点自己也更擅长(否则大概是自我认知有偏差了,最好还是找对自己擅长的方向)。
退一万步,有些公司要求就是低一些,有些公司真的只需要你踏实努力,不笨就行了,我就碰到有也不算差的公司coding题基本都是easy难度。
从概率上来说,不太可能你现在的公司就恰好是能给你最好待遇、最适合你的公司。所以只要坚持不懈,大不了找不到就继续一边上班一边准备一边继续找,早晚能找到可以跳的公司。

2.7 早期面试难免因为经验缺乏不顺利一些,这时候可能会在中期拿到第一个offer的时候冲动想直接签了,这个时候要冷静,要相信自己到后段真正理想的公司时会表现的更好。

希望各位大佬不吝赏赐些大米~
  • 704
53条回复