有朋友指出「三個月」是不是譁眾取寵博取眼球。其實我確實是實話實說(詳見下文)三個月。我只是想分享如何高效的做題,讓大家少走彎路。那些刷五遍十遍的朋友,在我看來是走了彎路的,如果大家都能一兩遍做懂,何樂不為?
本人背景介紹:
本科國內某211,EE major Power
碩士研究生USC CS General
實習經歷
Amazon Inc, Seattle, WA. 3-month intern
Tesla Motors, Fremont, CA. 4-month intern LinkedIn
簡歷的意義:簡歷到底有多重要?是不是要把簡歷寫的很Fancy?寫的比較多比較誇張會不會被問到?
對於New Grad來說,簡歷只是敲門磚,好的簡歷的目的是讓HR注意到你「哎喲,這個New Grad不錯,給ta安排一個面試吧」。所以,你的最終目的還是有面試機會。好的簡歷能夠幫助你通過機器篩選和HR的篩選,但是很多時候,簡歷普通也是可以拿到面試機會的。「簡歷普通」不代表「簡歷寫的差」,下面我會詳細說明一下。
一個優秀的簡歷大概的樣子:
Name: John Doe Email:jd@gmail.com Phone:xxx-xxx-xxxxEDUCATION: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, WAPosition: 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 XData 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<? super E> comparator)
constructor is initialized with capacity and compare rule.
3) Java anonymous class is used to simply create and use this comparator
4) The node inside list could be null
5) PriorityQueue use poll() method to pop out it’s first element
public class Solution { private static final Comparator<ListNode> comp = new Comparator<ListNode>(){ public int compare(ListNode x, ListNode y){ return x.val-y.val; } }; public ListNode mergeKLists(List<ListNode> lists) { if(lists.size()==0) return null; Queue<ListNode> 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<Integer, List<Integer>>
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)代碼很好地寫完之後,還有時間有思路的話,可以口頭聊一聊一些比較有創意的解法,展現智力優越性。
總結:好的面試過程就像給一個不會這道題的學生講課一樣。要想辦法十分清晰的給對方講懂。如果有不明白的地方就多溝通,這樣就算最壞結果你沒有完整的寫出代碼,那麼面試官也會覺得你思路清晰邏輯正確,雖然代碼能力欠佳。給你一個中等評分。儘量不要獲得差評。
Q&A1)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經驗之後再去你最想去的公司。谷歌面試較難,做好充分準備。
關於內推和」熟人「:僅就我所知道的谷歌而言,每周入職的Noogler (New Googler) 在150 - 200之間。公司對人才可以用「饑渴」來形容。在我看來,你簡歷(經歷,背景)優秀,刷題刷到位(不要當炮灰),我就願意推你。我認為不合適的,我自然會告訴你哪裡還需要提高。內部推薦系統只是填一個表格交一份簡歷而已。HR會再次審核,ta看完簡歷之後再決定是否給你聯繫,是否把你放入面試的pipeline。我只推薦well prepared的人。熟不熟沒關係。
個人不推薦把Google當做第一個去面試的公司。谷歌的面試還是很有難度的,先面一些其他公司作為鍛鍊,對面試過程有足夠了解。
1、如果你滿足以下條件,歡迎聯繫我內推 If you think you are ready, shot me: **shaoyili@usc.edu with the following content:**
必須有:
簡歷.pdf
目前Leetcode的刷題程度
自我介紹:
簡單聊一下自己;
簡歷中最自信的proj;
自己的優勢;
感興趣的職位三個
(New Grad除外,NG的職位通常是 University Graduate - North America)
最好有: