一共參加了1次筆試,3次面試。總的感覺是,微軟暑期實習的筆試難度不算很大,面試難度隨面試官而異,畢竟是微軟,卧虎藏龍的地方,面試官想虐人還是非常容易的。
1.筆試
筆試挺簡單,雖然2013年的題和2012年的一點也不一樣,但是大體思路是一樣的。前面一部分簡單題是考C,C++基礎知識的,后面一部分是考算法、概率、信息論等稍微高一些的理論的。全是選擇題,答錯、不答扣分,少答給一部分分數,全部答對才得滿分。考前我看了點C++ Primer,算法導論一直在研究,所以后面答的還不錯,基本沒錯,前面的就比較慘了,C++用的太少,錯了好多道。不過微軟筆試設的門檻不算高,按照網上的答案我卷面大概有70分,不過40分左右應該就可以進面試了。
2.一面,二面
微軟的一面和二面是在一起的,兩位面試官,每位面一個小時。規則是:如果兩位面試官都對面試者滿意/不滿意,面試者直接拿到offer/被淘汰,如果兩位面試官意見不統一,會在幾天之后安排加面,也就是三面,最終的錄取結果會在一段時間后通知(今年是五一之后,被淘汰的好像不會收到通知)。我被安排在了4月21日下午面試,面試時間是根據什么安排的眾說紛紜,這個也不好揣測,可能微軟有自己比較復雜的算法吧。在這之前,Jeans和我gf分別在前一天和上午進行的面試,他們面試的情況比較相似,都是以問算法和數據結構題為主,題的難度是由淺入深,開始的簡單題例如:斐波那契數列、判斷平衡二叉樹、鏈表反轉、字符串轉整數等都需要編程,而后面的一些復雜題或者開放性問題只要求說出算法,不太需要實際的編程。然后我抱着這種心態去參加了下午的面試,沒想到完完全全被虐了。每個面試官只問了一道題,也就是說,一上來就是比較難的題,完全沒有簡單題熱身。
第一個面試官首先看着我的簡歷問了一些問題。然后看到我在android手機上寫過一個程序,問我這個程序是否考慮過擴展性和移植性。我大致講了一下我在設計程序的時候是怎么考慮這些問題的,接着掏出手機給他展示了一下,他說做的挺酷的,然后簡歷部分就結束了,詢問簡歷這部分大概只有15分鍾。接下來就是做題了,他出的題目是“輸出排序二叉樹任意節點的后繼”,其實這道題不算很難,就算不能完全寫出程序,大致框架寫出來應該是沒問題的,只是我當時生病&緊張,一上來就問這種難度的,和預期的差距太大,心里有點慌。自己寫了大概20分鍾,寫得不是很對,然后他稍微提示了一下,我又根據新的思路寫了20分鍾,不過一直到最后,也沒有把完整的程序寫出來。后來想了想,思路有一定難度,程序編起來也比較費勁,思路如下:
節點的后繼指的是二叉樹中序遍歷時,該節點之后遍歷到的節點。分兩種情況:
1.如果該節點有右子樹,則后繼是它的右子樹中最左邊的節點。
2.如果該節點沒有右子樹並且該節點是它的父節點的左孩子,則后繼是它的父節點。
3.如果該節點沒有右子樹並且該節點是它的父節點的右孩子,則后繼是滿足“距離它最近的、左孩子也是它的祖先的”祖先節點。如果找不到這樣一個節點,那么該節點沒有后繼,即該節點是排序二叉樹中序遍歷的最后一個輸出。
回學校之后我在網上找了一下,只找到一個大概80行的代碼實現,不過這個實現是給排序二叉樹加上了parent指針。按照正常的二叉樹來做的話,還需要維護一個棧來存儲祖先節點,代碼量應該有100行左右。
第一面就這么悲慘的結束了,感覺自己完全被虐了,其實還是自己的准備不太充分,而且狀態不夠好。
接下來是二面,也是一位難對付的面試官。上來看了一下我的簡歷,基本沒問什么,直接就開始做題。題目是:設計一棵多叉樹,即一個節點可以有多個孩子節點,不允許用二叉樹方法表示。我是從來沒有見過&做過類似的題,只能硬想。我提出用孩子,兄弟表示法,但是他說這就是個二叉樹,所以不可以。然后我又向他確認了每個節點的孩子數量是否有最大限制,他回答可以有。又想了一會,我把自己的想法整理了一下,跟他說了。簡答來說,就是每個節點有幾個域:一維父指針、二維孩子指針(存儲所有孩子節點指針)、key值。他不置可否,讓我繼續寫一個刪除某一節點的操作,我寫完之后他又要求輸入是根節點,我就又加了一個遍歷樹的功能。總算是全部都寫完了,他說讓我分析一下我的代碼有什么沒考慮到的地方,我指出了幾點:需要刪除節點、根節點為NULL,需要刪除節點不在樹里面,需要刪除節點的孩子數量+需要刪除節點的父節點的孩子數量大於最大數量上限等等。他聽了之后,啥也沒說,這道題就這么結束了。剩下的二十分鍾,他就隨意問了我一些簡歷里面的東西,讓我講解一下adaboost分類器,分析剛才題目里面操作的時間復雜度,甚至還問我怎么看待自己的編程能力。……然后二面就在非常冷氣氛中結束了。總結下來就是,他問我,我回答,他無反饋,我問他,他不高興。
那天走出微軟大廈的時候真心感覺和微軟無緣了,呵呵。
3.三面
一面二面之后我以為沒戲了,沒想到微軟給我發了三面通知。三面一共一個小時,面試我的是一位女面試官。跟之前一樣,首先問了大概5分鍾的簡歷。然后就開始做題,題目如下:
1.兩個均大於3的連續奇數,並且都是質數,證明兩個連續奇數中間的那個數可以被6整除
解:這是一道數學題,首先,兩個連續奇數中間的書肯定是偶數,必能被2整除,因此問題簡化成證明中間的這個偶數可以被3整除。因為兩個奇數都是質數,因此兩數都不能被3整除。假設第一個奇數除以3之后余1,那么因為第二個奇數比第一個奇數大2,因此第二個奇數除以3余1+2=3,因此第二個奇數可以被3整除,這與條件矛盾。所以第一個奇數除以3余2,第二個奇數除以3余1,那么兩個奇數中間的那個偶數一定能被3整除,一個數,即可以被3整數又可以被2整除,一定能被6整除。
2.有大量的無序浮點數,取值范圍從0到1000,怎樣找到這些數的中位數
解:方法類似於桶排序,假設數字的總數量為N,那么根據N的大小,分配每個桶的容量,保證桶的數量不至於大到無法裝入內存,並且桶的容量盡量的小。然后將數據依次放入桶中,接下來從最小的桶開始,逐個累計每個桶中數的數量,如果加到第i個桶時,數量首次超過了N/2,那么中位數一定在這個桶中,假設這個桶中浮點數的數量為k,累計的浮點數總數為m(不包括第i個桶),那么只要在這k個數中尋找第(N/2-m)大的數即可。用快排的partition方法就能在o(log k)的時間復雜度內找到。
3.雙向鏈表的逆轉
這個比較簡單,就不說了,只要代碼寫的沒問題即可。