本文仅以个人经历和个人观点作为参考。如能受益,不胜荣幸。
本文会不断的修正,更新。希望通过大家的互动最后能写出一份阅者受益的文章。
本文纯手打,会有错别字,欢迎指出,虚心接受及时更改。
小马过河,大牛觉得轻松,松鼠觉得可怕。
湾区求职经验分享:我是如何通过三个月努力拿到Google offer,欢迎踊跃提问!
有朋友指出“三个月”是不是哗众取宠博取眼球。其实我确实是实话实说(详见下文)三个月。我只是想分享如何高效的做题,让大家少走弯路。那些刷五遍十遍的朋友,在我看来是走了弯路的,如果大家都能一两遍做懂,何乐不为?
本人背景介绍:
实习经历
简历的意义:简历到底有多重要?是不是要把简历写的很Fancy?写的比较多比较夸张会不会被问到?
对于New Grad来说,简历只是敲门砖,好的简历的目的是让HR注意到你“哎哟,这个New Grad不错,给ta安排一个面试吧”。所以,你的最终目的还是有面试机会。好的简历能够帮助你通过机器筛选和HR的筛选,但是很多时候,简历普通也是可以拿到面试机会的。“简历普通”不代表“简历写的差”,下面我会详细说明一下。
一个优秀的简历大概的样子:
Name: John Doe
Email:jd@gmail.com
Phone:xxx-xxx-xxxx
EDUCATION:
08/2014 - 05/2016 University of Southern California (USC)
M. S. in Computer Science Los Angeles, USA GPA: 3.80
......
//这个没什么说的,简单明了就好
EXPERIENCE:
2015/05-2015/08 : Amazon Inc, Seattle, WA
Position: SDE Internship
- Design and develop a realtime data aggregation workflow...
- Use AWS Kinesis to consume the original chunk of data...
- Develop a Java data processor that runs on AWS EC2...
2014/07-2015/01 ......
//写一下自己曾经在哪工作/实习过,大概做了什么内容用了什么技术。
PROJECTS:
Web Search Engines on Arctic Data Information Retrieval
- Build a search engine based on Apache Solr for polar data analyzation.
- Design and develop web crawler to fetch data from polar science website
- Use SimHash algorithm for near-duplicates deduplication.
- Build a web search engine and apply page rank.
......
//需要对project技术性的描述。项目名称,之后以bullet point的形式写用了什么技术,实现了什么东西。
SKILLS:
- Programming Languages: Java, Python, PHP, JavaScript
- Operating Systems: RHEL, Debian, Mac OS X
Data Analysis: Hortonwork; AWS EC2, S3, CloudWatch, Kinesis; NoSQL, RDB
- Web: LAMP
......
//SKILLS的建议是,不要写自己不会的,你写Python就要期待面试会用Python面你。任何写在SKILLS上的东西都会被问到。
总结:
标准是:任何写到简历上的东西面试官问道都可以详尽流畅的表达清楚。用了什么技术?哪些service?“看你简历写用AWS EC2了,给我详细讲一下AWS EC2和你使用的时候遇到的困难”这类问题。
实习的重要性:
如果说一个“完美的简历”是100%的话,一个好的工作/实习经历决定了这份简历的50%-80%,如果可以尽量去大公司实习,尽量多去几个不同的公司实习。除了实习之外:论文、Project、名校会分剩下的20%-50%。4.0会是一个小小的Plus,除此之外在3.0-3.9之间没什么区别,但是不要低于3.0,其实除了Oracle之外没多少人会看GPA。
如果说你没有实习经历,最好的建议是用从现在到毕业的这段时间给自己多找几个实习。
如果说你已经毕业或马上毕业没有时间实习,那么就把在学校做过的Proj多写一些。
三个月的过程:
2015年12月从特斯拉实习结束,到2016年4月面试完谷歌,一共四个多月时间。元旦给自己放了两周假期,过年给自己放了两周假期,中间再穿插着出去玩。连续的用在刷题的日子大概有三个月。我是每天“全职刷题”的,分派给每天的任务(x道题)会被我分成上午a道,下午b道,晚上c道。如果提前完成,剩余时间自由支配,放松一下。
从2015年12月开始刷题,就给自己制定了一个做题计划,在衣柜的镜子(没有白板-。-)上制作了一个表格,这个表格是我每天自我check的参考。原计划是两个月做完所有题(约340),但事实是一直到找到工作也没有真的做完所有题。最后做了250道unlock的和所有lock的题(我们几个朋友合买了一个leetcode会员)。
我之前的基础:
本科没有学过编程,研究生上的算法课也上的不是很懂,很多课堂上的概念反而是刷题的时候才理解。
2015年初,在面Amazon Intern的时候刷过一次题,做了大约100个 easy 和 medium。在学校一边上课一边做题,三天打鱼两天晒网效果不好,只学了个皮毛。
2015年底翻看做过的题,基本忘光了。干脆搞个新账号重新开始。这次是每做一道题进行一次总结。翻看leetcode的热门评论,把自己的解题思路和别人比自己写得好的解题思路都详细的记在笔记本上。遇到一道新题就尝试理解,归类,翻出老题做对比,写code,看热门答案,更正、优化自己的答案,为什么他能想出这个解,搜一下相关不熟悉的知识点。
这个方法开始起步会特别慢,没有什么成就感。但是效果出奇的好,刷了一半,只要做过的题,理解的十分透彻。遇到一个考到的算法或者数据结构,比如trie tree,就会回去看所有trie tree分类的题,主要是看题目,回忆解法,如果想不起来或者不是很自信,再写一次。反之很熟悉,脑子里过一遍就继续下去。看完trie tree也会想到Binary Search Tree, Segment Tree, Binary Index Tree。脑子里对这些数据结构过一遍。
这样做题到后来的感觉就是,everything is connected. 随便给一个题,就能找出这个题和什么题是类似的,或者其本质是这个算法的变形。简而言之,明确的感觉到,自己学懂了。
刷题是枯燥的,如果你想着用毅力用坚持,只会让它更枯燥。毅力是必须的但是坚持往往是痛苦的,何不让这个过程变的快乐。这个年代人人都是千里马,但是伯乐不常有。我们只能做自己的伯乐,给自己制定最合适的训练方法,因人而异因地制宜,自己既是“运动员”也是“教练”,毕竟还是自己最了解自己。时不时给自己一些奖励,给自己放一个小假出去转转。
其实辛苦几个月,没那么难。和农民伯伯一样,种地是辛苦的,可是丰收是喜悦的。当你发现你努力了一个月之后,做过的题可以得心应手,还可以给别人讲的头头是道,还是十分有成就感的。毕竟才几百道题嘛,比上高考差远了。做到炉火纯青很难,但是得心应手还是指日可待的。
怎么刷题:
最多被问到的问题是:刷题刷多少遍才够?我想说,答案因人而异,我一遍都没刷完,感觉就够了。因为刷题的目的并不是为了刷多少遍,而是为了做懂题。举个例子,参加过高考的都知道,高考是不会出你做过的题的,那做《5年高考3年模拟》还有用吗?答案是肯定的。刷算法题和做高考练习题的意义是一样的,你的目的是理解出题人想要考你什么,如何解题,几种思路,最后写出最优解。
如何“一遍都没刷完”而做懂题?
“善于总结”是核心。还是拿高考举例子,“不会做的题和做错的题”远比“做对的题”有意义,只有从错题中才能进步。做算法题也是一样的,不要在烂熟于心的题上面浪费时间,把时间用在错的,不理解的题上面。
拿到一道题,怎么做?
就拿Merge k sorted Lists这一题举例子:
Merge k sorted linked lists and return it as one sorted list. [Java]
1) First think about a simple merge idea. Go through k head elements each time, they are the smallest among their list, k pointers and totally nk elements.
time: O(nk^2) space:O(k);
[CODE] 略,自己写一下把,这个简单
2) Use heap. This is a classic question for heap. each time we change a heap value we only use Log(k) time
time: O(nkLogk) space:O(k)
1) A comparator used can be passed to Collections.sort(coll,comparator)
2) In java, heap is implemented as PriorityQueue. The constructor
PriorityQueue(int initialCapacity, Comparator
public class Solution {
private static final Comparator comp = new Comparator(){
public int compare(ListNode x, ListNode y){
return x.val-y.val;
}
};
public ListNode mergeKLists(List lists) {
if(lists.size()==0) return null;
Queue heap = new PriorityQueue(lists.size(),comp);
for(ListNode node : lists){
if(node!=null) heap.add(node);
}
ListNode dummy = new ListNode(0);
ListNode p = dummy;
//heap did not implement isEmpty method
while(heap.size()>0){
ListNode node = heap.poll();
if(node.next != null) heap.add(node.next);
p.next = node;
p=p.next;
}
return dummy.next;
}
}
1、这一题明显是考Heap的,如果对Java PriorityQueue不够了解的,就应该去复习一下。Java7和Java8不太一样,Java8在传入comparator不再需要给定size。
2、代码中写到了Collections.sort()
,和在sort中写匿名类。
3、为什么要写dummy?在那些题中需要写dummy而return dummy.next。那些题不需要?
4、为什么用Queue interface,用List->LinkedList可以吗,是否要复习总结一下list,queue和它们的implementation? 如果对Object Oriented 不熟悉的,是否要再看看继承(Inheritence)和多态(Polymorphism)。那再往深处想一想,Abstract Class 和 Interface 的区别,优缺点呢?
这些 Java 基础就是做题的时候要想,不是很理解就要及时解决。基础不好的同学,刚开始做会比较慢,所以一道题做完过去了大半天,这很正常,等做多了,烂熟于心了,做题就快了。每次做题也都是对知识点的强化。
代码[CODE]部分和代码上面我自己的思考笔记都是写在Evernote上的,每次写完代码要把遇到这个题时候的想法,解题思路,看完别人答案之后自己的理解,基于答案对自己code的改进写进去。
Design:
Design可以基本分成Object-oriented Design(OOD)
和 System Design(SysD)
. 简单说一下我的理解:
OOD: 面向对象设计,顾名思义,针对开发过程中的结构,关系,逻辑进行设计。比如说:设计电梯;设计五子棋;设计各种游戏等
SysD: 更多是scalability侧重。比如:DB(Master-slave),sharding,Cache(Redis, Memcached), Load-balancing等等
OOD 推荐:
SysD 推荐:
hiredintech
http://highscalability.com
一个很不错的帖子:https://www.evernote.com/shard/s576/sh/7e58b450-1abe-43a8-bf82-fbf07f1db13c/049802174415b418a2e65f75b744ab72
1、 这个准备可是没有尽头的。对New Grad来说没必要在这上面投入太多时间。我用了两周时间,OOD和SysD各一周。
2、SysD把hiredintech网站的这个教程看两遍,尤其是Harvard 的那个1小时45分钟的视频,我先后看了三遍。第一次完全不懂讲什么,只是记笔记听课。然后上highscalability.com 看了几个例子。搜了搜所有视频里介绍到到概念。再看第二遍1.5倍速,基本理解透彻。面试前2倍速看了一半,回忆一下。
3、 OOD没有尽头。最起码记住,理解,会用Singleton和Factory这两个。剩下的吹牛逼就行。OOD很少有绝对的正确或者错误。通常看你能不能说出这样设计的优点和缺点,选择的得失。
4、不要在design上面花太多时间。这东西,你不用也记不住,也不理解。抽出两三周好好理解几个例题就好,记笔记,onsite之前再复习一下。
5、 SysD我跟着Harvard的lecture画了一个有普遍适用性的图,不同的公司/业务scalability都可以套用。仔细看lecture。
面试Pipeline:
HR安排面试 -> (HR聊天) -> (OA) -> 电面 (x 2) -> onsite -> (加面)
备注:(括号内容)或许有,或许没有。
最关键的是如何让HR把你放进pipeline,给你安排面试。有几种方式:海投 < 校园招聘 < 内推< 直接和 HR 联系
所以说,最好的情况是,HR主动联系你。说明ta对你感兴趣。那么ta一定会给你安排进面试pipeline。那么如何做到让 HR 主动联系你呢?
1、优秀的简历(经历);
2、 LinkedIn Allstar;
3、Hackathon,Hackerrank 等活动/平台比较出众;
4.、从有面试的人手里获得 HR 的Email,主动和 HR 联系,毛遂自荐。
1和4结合效果最好。推荐大家把简历写好,然后从你周围面试的朋友那里要到 HR 联系方式,然后毛遂自己。
主动联系HR:
前文说到,能直接和 HR 联系是最好的。简单粗暴的方法是,从朋友那里要到 HR 的联系方式,主动发 Email 过去,自我描述外加简历。通常 HR 都会很快的回复你。
标题可以用:Strong Background Candidate You Might be Interested.
内容:简单介绍一下自己,和自己做过的proj。感觉和贵公司方向/产品/文化很match。
附件:简历
最好是直接联系校园招聘的 HR。HR的 level 和 focus 有很多,有些是专门招聘大牛的,工资,面试等都是单独谈的。有些是面对New Grad。有些面对普通跳槽的。有些公司HR是跟组的,比如Apple,某组的hr专门为这个组来找人。
通常情况下,如果HR认为你不match,会给你推荐给你对应level的HR/别的组的HR。
电面:
电面“通常”比Onsite简单,但是这个“通常”在Google Uber等“比较火”的公司这里不适用。Google的面经可以说“深不见底”,所以如果你是aim the top的话,还是推荐把题目做到融会贯通。
Onsite:
个人感觉onsite没有必然比电面难或者简单。出什么题,随机性很大。一个面试官大概有准备的题会有三五道,ta通常从自己熟悉的三五道题里出题来考你。
考核的内容是:
对问题的抽象和理解:这里期待你回答的内容是:”这道题可以抽象成拓扑排序,有些步骤需要在其他步骤之前执行,如果没有形成cycle那么整个就能完成。” 能够庖丁解牛的把这道题的本质分析清楚,剩下的就是实现了。当然,有些题没有见过,猛一看并不能说出个一二三来,那么就需要和面试官沟通了。
沟通能力:如何同面试官沟通?遇到一个没有见过的题,或者遇到写到一半写不下去卡了,这时候就需要“试探”面试官了。假如遇到一个有关比较大小的题,你不会,你总能想到 1排序 2DP 3divide conquer 那么你就说,目前我有几个不成熟的想法:1,2,3. 但是不确定哪个更合适,你怎么看?一个通情达理的面试官立刻就理解了,他会说,可以从排序试试。这里的核心思想是,不要不会就不说话,要去旁敲侧击试探性的提出几个假设,看面试官怎么回答。
Coding:和面试官“商量”的差不多,确定了思路,就可以开始写了。写代码其实没什么说的,刷题都刷够了。这里的建议是,白板写代码最好自己带笔,我面试都是自己带“粗细程度为fine的黑红蓝绿白板笔”(amazon买的),因为细一点的笔方便我写的清楚,节约白板空间,减少涂抹,清晰好看,和面试官讲自己代码时候用另一种颜色,清晰明了。
再有就是代码风格“努力让每个函数在20行之内”,能单独写成一个函数的尽量单独写出来,因为白板都是长宽的,竖着写得多了再拐弯就不好看,容易出错。比如 isGraphVerticallySymmetric()
Given a list of dots, return true iff the graph in the dot can form a vertically symmetric graph.
EX:
0 0 1 0 1
0 0 0 1 0
0 0 0 1 0
0 0 1 0 1
return true;
0 1 0 1 0
0 1 1 0 0
return false;
分析:
For each x, find all it’s y and put it into a list. HashMap>
For each x, calculate its list of y's symmetric middle point.
If pre_middle_point != cur_middle_point return false.
那么分析中可以看出需要两个独立的函数,结构如下:
isGraphVerticallySymmetric()
preProcessGraphToMap()
calculateAndCompareMiddlePoint()
calculateMidPointOfList()
而isGraphVerticallySymmetric()
分别调用这两个函数就能完成判断。写calculateAndCompareMiddlePoint()
中发现可以单独再写一个calculate的函数,compare比较简单就在calculate函数之后做判断即可。[这一题挺不错的,建议大家自己写写加深理解]。
那么白板上应该有四个函数,每个函数都不会很长,逻辑清晰,代码明了。(optional)代码很好地写完之后,还有时间有思路的话,可以口头聊一聊一些比较有创意的解法,展现智力优越性。
总结:好的面试过程就像给一个不会这道题的学生讲课一样。要想办法十分清晰的给对方讲懂。如果有不明白的地方就多沟通,这样就算最坏结果你没有完整的写出代码,那么面试官也会觉得你思路清晰逻辑正确,虽然代码能力欠佳。给你一个中等评分。尽量不要获得差评。
1)Q:几月份开始投简历,几月份开始面试比较合适?
公司与之间公司不一样,Google, Uber, Amazon这一类的“人才饥渴”的公司是一年四季都在招聘的。而大多数小公司是按人头招聘的。
2)从开始投简历到面试,中间时间能否充分刷题?
建议做题做到基础知识扎实(比如上面讲的从一道题回忆java基础)Leetcode Easy和 Medium都可以做懂,就可以开始投了。当然,hard题也是很重要的,但是刷题是没有尽头的,从开始投简历找工作到找到工作通常会有一两个月时间,这段时间一方面复习easy 和med,一方面做做hard刷刷面经。
3)学校career fair有多大意义?
有些同学是从学校career fair被招聘到的,但是我个人不是很建议在career fair上投大公司。
1、人多,扎堆,来CF的人也记不住你是谁;
2、你的目的是 HR 把你放进hiring pipeline里,开始面试过程,然而CF和这个关系并不大;
3、如果可以,在CF开始前半个月开始找人内推或者主动联系HR比较合适。
4)除了算法还面别的吗?
面试随机性很大,如果面试官想面你design那就面。从经验来看,Uber一定是会面design的,而FMAG(Facebook, Microsoft, Amazon, Google) 大概10%的概率会面你design。
5)特斯拉实习时候是毕业了吗?
USC可以选择最后一个学期全职实习,所以那是我最后一个学期。我个人不推荐毕业之后还去实习。如果可以,尽量拿full time。
6)能否分享一下面经?
Sorry, 签订了保密协议,而且自己也是实名写这个经验贴,不方便分享面经。
7)您当时也是EE2CS这么一个过程 就是能否请问本科结束到去美帝之间这段时间 请问您有做什么准备 以及如何去自学相关的CS知识呢? 通过什么样的途径 需要学习些什么呢?然后到了美帝以后又该如何进一步地提升自己的实力以及相关CS的知识储备呢? 以及怎么去多做一些Project呢?
当时自学java,python,数据库等。后来发现还是差的太多。研究生第一年非常痛苦,每天白天上课晚上自己补习白天不会不懂的知识点。第二年就好多了。学习的方法我觉得大家都知道,无外乎挤出时间补足自己的短板吧。所有知识储备也都是基于学校课程,刷题和实习。
8)想请问下刷题如何能做到举一反三?我目前的问题就是碰到新题目没有思路,不知道如何开始写?请问你在这方面有什么经验吗?
“遇到新题没有思路”一般是这个题型没有见过。如果是比较偏的,冷门的题型这很正常,总会有没有见过的题。但是如果看答案之后发现是常用的数据结构、考点、算法、那么就说明是自己掌握的还不够。针对: Array, BFS, DFS, Backtracking, Binary Search, DP, Graph, Hash Table, LinkedList, 各种tree (Segment, Tire, Binary Indexed), Topological Sort 等常见类型的题都应该熟练的掌握。
9)地理位置优势,性别优势?
从周围的朋友的面试观察来看,确实存在地理优势和性别优势。
1、如果你距离公司不远,比如公司在湾区,你也在湾区。公司会更愿意给你面试机会,对于公司来说成本低。这个现象在小公司尤为明显,小公司hr是要考虑节约开支的。大公司好很多,你只要优秀,总会给你面试机会。
2、如果你是女性,那么恭喜你,你比男性程序员有优势。无论是公司会想办法平衡那女比例,还是大部分面试官看到女性都会有“手下留情”,这两方面来看。我知道的周围的女性程序员,bar通常比男性程序员低一些。(只是低一些,你真做不出来谁也帮不了你。可能会面试题不那么变态,想不出来多给你一次提示 etc)
10)楼主在面狗家之前面过几个onsite啊?
没面过,谷歌是我第一个真正意义上的onsite,之前tesla的return offer onsite也没有考什么技术或算法。不过我十分不推荐把谷歌放在第一个来onsite。有一些onsite经验之后再去你最想去的公司。谷歌面试较难,做好充分准备。
11)More coming
······
关于内推和”熟人“:仅就我所知道的谷歌而言,每周入职的Noogler (New Googler) 在150 - 200之间。公司对人才可以用“饥渴”来形容。在我看来,你简历(经历,背景)优秀,刷题刷到位(不要当炮灰),我就愿意推你。我认为不合适的,我自然会告诉你哪里还需要提高。内部推荐系统只是填一个表格交一份简历而已。HR会再次审核,ta看完简历之后再决定是否给你联系,是否把你放入面试的pipeline。我只推荐well prepared的人。熟不熟没关系。
个人不推荐把Google当做第一个去面试的公司。谷歌的面试还是很有难度的,先面一些其他公司作为锻炼,对面试过程有足够了解。
1、如果你满足以下条件,欢迎联系我内推 If you think you are ready, shot me: *[email protected] with the following content:*
必须有:
自我介绍:
感兴趣的职位三个
(New Grad除外,NG的职位通常是 University Graduate - North America)
最好有:
2、如果你现在在湾区或者未来计划去湾区从事编程工作,欢迎加入微信群聊,加diycode.cc 社区发起人微信,他会拉你入群(微信号:jixiaohua888,备注,湾区交流)
首先澄清这里不是说“理工科 > 文科”。这里只是说一种思维方式。这部分和面试没有直接关系,但是个人感觉这是从开始学习编程,到现在,这三年最大的收获。简单粗暴的来说是:遇到一个问题,抽象这个问题,这个问题大概分为多少小的目标,如何达成一个个目标从而解决这个问题。
举例:1)面试算法题
抽象:
遇到一个算法题,这个算法题可以被抽象归类成另一种题。化未知为已知。
比如,Find the Duplicate Number 的本质就是Linked List Cycle。大家可以做一下理解一下。
再比如,横着做 two sum, three sum, four sum, 3Sum Smaller 等题目。理解他们相同和不同是什么。
划分 小的问题不需要划分,但是大的问题,复杂的问题通常需要划分成一个个小的问题去实现。比如上文Onsite分析的那一题,就是把一个复杂的问题分为几个小问题去解决。分别把小问题解决之后,整个大的问题也就得到了解决。这样做更有逻辑更清晰,不容易出错,化大为小各个击破降低难度。
举例:2)毕业生刷题找工作
问题:
毕业需要找工作,找工作需要刷题。
抽象
化未知为已知。刷题没有做过,但是中考考高还是经历过的。那时候对于做题,练习,准备考试的这一套方法应该依然适用。
划分
也相当于制定计划。我计划三个月找到工作,那么我先制定一个两个月的计划,一方面留有裕量,另一方面好的复习应该两三轮,那么剩下的的时间再来复习一次/两次。
指定具体计划,前几周先把easy和med的做掉,因为效益最大化原则,用最少的时间做最大的cover。后面对简单题理解充分之后难题就不那么难了。
把任务分到每天做什么,每天的任务分到上午做什么,下午做什么。晚上根据情况可以有bonus。充分利用每天的时间。
实现
奖惩机制,完成要对自己有所奖励,物质/精神。没有完成要写下为什么没有完成,可控因素,不可控因素,计划制定不合理等。
过于难的题可以推后/放弃,时间有限,如果需要将来再回头做说不定就迎刃而解。
这个世界上太多千里马,太少伯乐。与其等待伯乐,不如做自己的伯乐。
举例:3)其他
马拉松,这个相比不用多说,马拉松哪怕是对于专业运动员也是超出人类极限运动。把26 mile划分成26份,每次完成1 mile就对自己进行一次肯定。心中永远只有下一个目标。
schedule;大公司的业务制定和实现,KPI考核;国家的“五年计划”;
总结
1) 凡事预则立,不预则废。
2) 一个优秀的人应该具有很好解决问题的能力。遇到问题,分析问题,划分问题,执行力。
3) 不要乱了阵脚,胡子眉毛一把抓。计划才能高效。
4) 计划赶不上变化,不断调整。不断调整算法,达到实时的最优解。
CS学多了
1)出个门都想着路线最优解,出去一趟,顺便取个信,丢个垃圾。怎样路程最短。
2)做什么事,本能的会在脑里子列举0,1,2,3,4个步骤去解决。
3)总会想这个事会不会有edge case。
4)考虑周全,留有余地: extensibility, scalability。
5)受不了别人问问题不先Google。
6)受不了阐述不清晰。(说一个面经两句话说完了,没有完整的把题说完,没有例子,没有自己的理解)
这些都是编程里深刻理解到的,发现对现实生活也很有帮助。
共勉。