# 怎样把自己刷进谷歌

Copyright@ coding666.com

TLDR:本文想从一个过来人(面试者和面试官)的角度解析一下程序员刷题这件事情。希望能够给社区里的朋友们一些帮助。 本文的方法特别针对要在一到六个月内要面试谷歌的candidate。其他科技公司面试也适用。如果你没有时间读完,你只需要做到一条。

  • 反复刷LeetCode上面谷歌近六个月的面试题,保证80%都能做到15分钟bug free。
  • (optional)至少找人模拟面试一次,知道哪里好,哪里不足,胜率有多少。

# 公司想招什么样的人

其实对面试者的期望总结成一句话,就是把你找来你能完成我们的工作。那么工作中希望你有哪些素质呢?去看看职位介绍就知道了。但是职位介绍写的太抽象,不够直白,我看不懂怎么办?那么我来帮你对比一下谷歌官方的面试样板 (opens new window)

# 素质一,不清楚的要勇敢地问清楚

先看一下这个面试样板,首先interviewer给出一个问题,这个问题被描述的很简短。candidate对问题进行的clarification,输入的类型,输出的类型等等。这对应到实际工作中就是你遇到一个项目/问题是一定要知道自己要做什么,不清楚的时候去问人,确认自己的想法,先要把问题定义好了。其实这可能是最重要的一步。高等级的程序员每天也就在做这件事情,而不是具体的实现方法。

# 素质二,提出解决方案并听取团队意见

需求了解清楚以后,candidate给出了一个proposal,并且得到了interviewer的认可。对应于实际工作,你需要给出解决方案,并且跟team member收集反馈信息。并且根据反馈信息修改方案。

面试中,这个方案就是你准备用到的algorithm and data structure。你是否了解这些数据结构和算法,能否使用最合适的方法来解决这个问题,你是否熟悉算法,能不能拿你propose的算法来和别的可能也行的算法做比较,并且说出各自的优劣且做出合适的选择。这些其实也都对应到工作中解决问题时提出possible solutions。

# 素质三,快速准确按计划完成任务

然后就是implementation,可以看到,candidate写的并不是很快。但是一步一个脚印,思路清晰。做完之后有follow up,并且用同样的方法(提出解决方案然后实现)解决。

软件公司对程序员的期望是写的快,对code workflow有清晰的了解,少弄点bug出来,有bug了自己能看出来,写出readable code。了解implementation的算法复杂度,时间空间,给出评估以及改进方案。

# 怎样通过面试=怎样成为公司想要的人

在面试中,candidate的首要任务就是表现出以上这些素质,在coding面试中,可以具体表现为

  • 通过提问弄清楚interviewer想要什么
  • 应用合适的算法和数据结构
  • 熟悉所用的编程语言,能够用到该语言的新特性
  • 能够快速完成程序,尽量避免bug
  • 能够流畅的交流,尊重面试官的反馈意见

以上每条都是谷歌衡量candidate的标准,且一定会进入面试报告。现在有了具体的目标,看看如何通过训练获得这些素质。

# 素质一,不清楚的要勇敢地问清楚

做leetcode题目的时候读完题目先想一想有哪些clarification question,比如edge/corner case/size of input/ API 被call的次数 ,然后再看LeetCode题目最底下的Constraints,以及LeetCode给出的例子。不要一下把题目读完,浪费训练自己的机会。

# 素质二,提出解决方案并听取团队意见

# 解决方案=算法和数据结构

每条题做完后不论对错,都看看leetcode上的讨论,了解一下别人都用了哪些算法,各有什么优劣,怎样做选择。遇到新的方法,到网上搜讲解,看参考书introduction to algorithms。这样你知道了更多的alternatives,方便跟interviewer讨论。

# 听取团队意见

自己有新的解法去找人讨论,或者在leetcode上发帖,收集feedback。把自己的code贴出来,或者送给别人review,获得feedback。然后看看怎样接受这些feedback。

# 素质三,快速准确按计划完成任务

这是唯一可以量化的素质。也是你需要花大量时间的。最终目标是leetcode上谷歌近六个月的250题

  • 看到后20秒能想清楚怎么做,包括big picture和具体怎么实现
  • 按2行/分钟的速度实现出来
  • 写出符合coding style的优美的code
  • 每题做完都能清楚地知道时间空间复杂度

要做到这几点,基本等于在背答案,背模版。但是这就是人学习的方法。我们的语言都是在重复模版,替换掉里面几个关键词。小时候的造句就是在训练模版。所以对刷题的训练方法是两分钟不会做的题就看答案,看完了20分钟写出来,超时了就过十分钟再写一遍,直到能达到速度要求,第二天再写一遍,过几天再写一遍,直到变成肌肉记忆。为何如此?面试你会很紧张,肌肉记忆可以帮助你不要花脑子去想太多的具体实现问题。比如sliding window的模版里面,左指针和右指针是包含当前index还是不包含。其实都可以,但是你有了自己肌肉记忆的模版以后,根本就不用想了。如果你要想,会花掉很多时间和精力,没有更多的脑子去想其他更重要的问题,实现速度下降,interviewer准备好的followup也来不及问了。所以总结起来,就是重复训练,肌肉记忆。

既然是肌肉记忆,那么实现速度和code长度会成线性关系。这样python就会天然具有巨大优势。目测行数是别的语言的60%-70%。

# 速成方法

很多时候方向比努力更重要。如果你心里想的是铁杵磨成针,那么不如早点放弃。针没磨成人磨没了。 这里我想用个例子说明一下问题。很多人下棋,下了一万盘还是入门水平,而六七岁的小孩跟专业老师学几个月,就可以轻松战胜大多成年野路子棋手。为什么,有老师教,努力的方向正确。

# 速成法一:找面试官模拟面试

很多人刷题越刷越迷茫,会不停地问自己,我这样到底行不行,有多大的把握?有时候你觉得自己行了自己不一定行。或者你觉得自己不行然后面试没有信心。这时候如果有一个Google SWE给你面试一下会很好。如果你不知道去哪里找,联系我。mock interview其实公司是允许的,而且鼓励。我在谷歌refer candidate的时候会HR会让我去多教教candidate怎么准备interview,去帮他们mock。谷歌内部也有full time SWE帮助intern mock interview,然后把面试报告给他们看,让他们知道和expectation相比,哪里做得好,哪里做得不好。而且mock interview的性价比其实很高。你就想想去了大厂以后未来五年的工资增长,少说也有30万。mock interview的花费比跟这起来真的非常值得。

# 速成法二:找高手Code Review

写一段时间code最好也把一些写的复杂的code发给interviewer做一下review,告诉你code哪里写的不好,有没有什么坏习惯,因为google coding style很读起来无聊乏味,我自己也是在谷歌内部无数的code review中建立起来的正确style。

以上做完,我觉得面试胜率至少95%。废话不多说,祝你成功。如果需要code review或者mock interview,或者有问题想问的欢迎联系我bjrebeccali@gmail.com。

# FAQ

# 如果我遇到很难的题目怎么办?

其实很多人都在想这个问题。我觉得尽人事安天命,刷完250题后最好看看近两年的题怎么做,不会做的学会了以后也重复到肌肉记忆的水平。如果这样还是遇到了不会做的题目,那么这个题目一定非常刁钻,这时候你就多要hint,积极讨论,争取弄出来。而且Hiring Committee看到太刁钻的题目也会给你降低标准,我见过一些案例是题目太难,没做出来但是讨论的不错也过了。

# 怎样写出优美的code

参照对应语言的Google coding style (opens new window),找有经验的人review。

# 怎样做到bug free

这是一个很常见的问题。每个人都会犯错误。我非常反感小时候老师说的一句话,你现在算错一个小数点,以后造航天飞机怎么办。如果是现在的我一定会告诉ta,造航天飞机的人一定也会犯错误,要用test process来纠错,设计fault tolerant的系统来减小影响。所以面试中写出了bug完全正常。你在写完后让interviewer给你两分钟检查一下,自己设计两个unit test case,肉眼进去走一遍code。看看是不是每种情况都cover到了,结果和你预期的一样不一样。这样既让interviewer知道你了解workflow,会做unit test,还能帮你自己扫除bug,做出bug free code。在leetcode的训练中,你也要做同样的事情。写完code不要run,自己用一两个例子进去走一遍,把里面的bug扫除。保证不会有implementation的错误(如果算法有错,那没办法)。第一要告别debugger,debugger非常容易让人产生思维惰性。第二实在debug不出来自己的错误就用print,想想哪些是关键的地方,关键的variable,那里的expected value是什么。实际工作中也没有太多机会用debugger,因为都是server code,很难在本地跑起来。大多debug都是通过在自己想的checkpoint加log然后看看log出来的值是什么。

# 为什么我题目都做出来了,谷歌面试却挂了

这种情况经常发生,作为面试官,我遇见过的情况包括

  • 比较简单的算法但是candidate没有能够很快自己想出来,我提示了以后还是需要反应一会甚至一步一步地讲给candidate听。
  • 代码里面bug非常多,但是candidate自己写完就扔哪儿让面试官自己想办法。正确的做法是写完了不要立刻claim finished,而是用简单的unit test进去走一走,确认是对的。
  • 非常straightforward的代码却花多于expectation(一分钟两行)的速度写出来。coding不熟练。
  • 给出来working solution但是不是最优解,我给提示问能不能更好却自信的觉得这就是最好的,忽略提示。建议leetcode做完题目看看讨论区别人的解答。
  • candidate动作太慢,我准备了一条基本问题和两个follow up,但是candidate用了45分钟把基本问题做出来了,follow up一条也没有问。