面試官,您要的快排

2021-06-29 15:52:28 字數 1612 閱讀 8451

今天看到 v2ex 上有人討論 社招還會問 「請手寫選擇排序演算法」 嗎?,看來還是有很多人關心的。結合自己最近面試的經歷,我可以明確的告訴大家,類似這種問題,只要你的工作經驗小於 10 年,基本上逃不掉。勸大家不如抽點時間早做準備。

面試中遇到問快排的,如上面那個帖子中的情況。你就可以上乙份簡式快排了,何謂簡式?最短的**表述快排的思想。

快排的思想,實質是分治法。基於什麼來分?找乙個支點來分,通常稱之為 pivot, 而這個分的過程稱之為 partition, 基於以上兩點,我們用遞迴的方式描述快排:

void quicksort(int arr, int l, int r) 

}

如何?簡單吧。有人說面試的時候手寫快排,如果提前沒有背下來的話,肯定歇菜。我不認為這樣基礎的演算法是需要背的,上面這個遞迴,如此簡潔,如此美,真的需要硬記?

有人說,這個好理解,關鍵在於 partition 如何實現。的確,partition 是快排的靈魂。clrs 裡採用了以尾巴為支點的策略,我在這裡與其保持一致:

void partition(int arr, int l, int r)
這演算法用白話說,就是從頭到尾迭代,和支點比較,大的不管,小的換。換了才往後看。最後支點戳中間,算是分界線。

3,7,8,5,2,1,9,5,4
這麼來一下,就成了:

3,2,1,4,7,8,9,5,5

^^^^^ | ^^^^^^^^^

然後同樣的手法分別解決兩邊,這樣遞迴的解下去。

其實上面的那份,已經可以解決面試中的問題了。但其實有很大的缺陷,如當所有元素都相同的情況下,partition 將一直返回 r, 遞迴的深度高達 n,每一次遞迴中 partition 又迴圈 n 次,時間複雜度直接飆到了 o(n^2). 這顯然非常的不值當。

於是我們覺得分兩份太粗,分三份試試?

5 7 4 3 1 2 6 5 5
也來那麼一下,成為:

431

2555

76^^^^^^^ | | ^^^

這就是三明治的原理了,左邊是小於 pivot 的,中間是等於 pivot 的,右邊是大於 pivot 的。中間部分不參與遞迴,分治的是兩邊。

我們需稍稍改變下 partition 的實現,顯然我們這次希望返回的兩個支點(左右邊界):

// 3-way partition

std::pair partition(int arr, int l, int r)

而 quicksort 也需要稍稍改變一點:

void quicksort(int arr, int l, int r) 

}

如果在遇到全部元素相同的情況,時間複雜度成功的減少到 o(n). 算是乙個突破吧。

其實 clrs 隨後還提到了以隨機位置為 pivot 的思路,我稱之為東北亂燉。那是只針對 pivot 選取的改變,基於上述**,改造起來是非常容易的。這裡就不做過多實現,留作感興趣者自己練習吧。

上述三道菜,基本能夠解決面試中可能遇到的種種情況了。讓面試官吃飽,很有必要~

面試你的面試官

大多數面試都是面試官從簡歷,學歷,經歷,技術,為人上對你 乙個求職者 一番拷問,以確定是否是他們想要的人。而這些對找到適合你的工作的確沒什麼用。某公司某職位需要你,而某公司某職位不一定是你想要的!如果你想找到適合你的公司 如果你想找到適合你的職位 記得面試你的面試官,沒錯!做出很重要的職業決定前,面...

面試官感悟

其實之前也面試過幾個人,但都是零星的跟著別人一起,我也只是偶爾詢問一兩句就結束了。昨天這是一場真正的大型招聘會,而且面試也是相當規範,面對的還是社招。對於我這種初出茅廬來說,這是第一次真正接觸參與的一場招聘會,想起要面那些比自己工作年限還長的人,心裡很沒底,有點小擔心和緊張的。當然一整天下來也算體驗...

面試官問題

解釋一些壓縮感知理論 壓縮感知是一種全新的訊號採集和恢復理論,它打破了傳統的奈奎斯特取樣定律,可以從更少的觀測訊號訊號中重建出高質量的原始訊號。其基本思想是,當訊號是稀疏或可壓縮時,我們可以通過乙個隨機測量矩陣將高維訊號投影到低維空間,再通過乙個求解優化問題高概率的恢復原始訊號。解釋一下壓縮感知磁共...