美團面試,我竟然輸給了氣泡排序……
點選上方“ 程式人生 ”,選擇“置頂公眾號”
第一時間關注程式猿(媛)身邊的故事
作者
倪升武
本文為作者投稿,如需轉載,請聯絡原作者。
前一陣子有個讀者在微信裡跟我聊了一件很有趣的事情,他去美團實習,面試讓他哭笑不得,因為敗在了氣泡排序上。
情況是這樣子的,當時和麵試官聊的感覺還可以,就在他覺得好像差不多快結束的時候,面試官給他扔了個題:“我這剛好有紙和筆,你來寫個氣泡排序吧。”
這位讀者心裡一慌,為什麼慌,倒並不是因為不會寫,因為作為一個程式設計師,氣泡排序基本上沒有不會寫的,而是事發突然,感覺不太妙。當時他是這麼寫的:
public void bubbleSort(int[] a) { for(int i = a.length - 1; i > 0; i--) { for(int j = 0; j < i; j++) { if(a[j] > a[j+1]) //交換,具體實現略 swap(a, j, j+1); } } }
果不其然,他寫了之後,面試官就問他,這種寫法有沒有什麼問題?能否繼續優化?結果還真沒答上來。(看到這裡,讀者們不妨也先思考下如何優化。)
今天就這個氣泡排序,我們再多聊幾句,迴歸一下經典。也希望以後有朋友實習也好,校招也罷,不要再栽在同樣的問題上了。
氣泡排序演算法的時間複雜度高,如果不清楚演算法複雜度如何計算,可以參考下這篇文章: ofollow,noindex" target="_blank">循序漸進帶你學習時間複雜度和空間複雜度。 但是氣泡排序簡單,基本流程是:每一輪從頭開始兩兩比較,將較大的項放在較小項的右邊,這樣每輪下來保證該輪最大的數在最右邊。如何實現?就如上面這位朋友所寫的那樣,基本上大家都會寫。
但是今天主要討論的是如何優化,有人可能會說,這是再簡單不過的演算法了,還有什麼好優化的?確實,上面這段程式碼沒有毛病,但的確是有可優化之處的。
我們可以假設一種場景,比如 8 1 2 3 5 7,進行一次排序之後,結果就變成了 1 2 3 5 7 8,那我們還有必要再像上面程式碼裡那樣繼續迴圈下去嗎?肯定沒有必要了,因為這已經是最終結果了。
那針對上面的程式碼,我們優化的點主要在於: 假如某一趟排序之後已經有序,我們需要減少排序的趟數 。否則就做了很多無用功。
針對這個問題,我們可以考慮在演算法中加入一個布林變數,來標識該輪有沒有進行資料的交換,若在某一趟排序中未發現數據位置的交換,則說明待排序的無序區中所有的項均已滿足排序後的結果。那麼就沒有必要再次排序下去了。可以如下改造:
public void bubbleSort(int[] a) { boolean exchange; for(int i = a.length - 1; i > 0; i--) { exchange = false; for(int j = 0; j < i; j++) { if(a[j] > a[j+1]) { swap(a, j, j+1); exchange = true; } } if(!exchange) return; } }
這樣就優化完了,其實程式碼邏輯很簡單,通過一個布林變數即可監控一趟過程有沒有進行資料交換。
氣泡排序最好的情況是初始狀態是正序的,一次掃描即可完成排序,所以最好的時間複雜度為O(N);最壞的情況是反序的,此時最壞的時間複雜度為O(N^2)。平均情況,每輪N/2次迴圈,N輪時間複雜度為O(N^2)。所以它並不是個好的排序演算法。 這個問題的討論就到此結束,如果有更好的優化演算法也歡迎留言討論。
氣泡排序並不好,但為什麼面試官還會去問?針對這件事情,我們需要注意什麼呢?
1. 經典的東西,可能已經不用了,但是從經典的東西身上,我們能學到的還有很多,否則也不會成為經典。特別是那些面試經常被問到的,總有它存在的合理性。
2. 教科書上的東西不代表實戰,所以很多時候考慮到非理想情況下,就可能不那麼適用了。面試官往往更加註重的是在不適用的情況下,面試者是如何應對的。面試官更加看重的是面試者的思路。
3. 應屆生不能浮躁,特別是在準備面試的時候,一定要步步為營,切忌好高騖遠,淺嘗輒止,多學習學習經典的資料結構和演算法( 最常用的經典資料結構和演算法彙總 ),多做做演算法題還是很有必要的。
- The End -
「若你有原創文章想與大家分享,歡迎投稿。」
加編輯微信ID,備註#投稿#:
程式 丨 druidlost
點文末 閱讀全文 ,看『程式人生』其他精彩文章推薦。
推薦閱讀:
-
OA==&mid=2247499310&idx=2&sn=8ccbb7c4ebc91b6ce277ab592299429b&chksm=e99ecdd7dee944c13c8441880ae472d0ff2c2501247859431044896a3f77333b1df437fdb84d&scene=21#wechat_redirect" rel="nofollow,noindex" target="_blank">公開課報名 | 詳解CNN-pFSMN模型以及在語音識別中的應用
print_r('點個贊吧'); var_dump('點個贊吧'); NSLog(@"點個贊吧!"); System.out.println("點個贊吧!"); console.log("點個贊吧!"); print("點個贊吧!"); printf("點個贊吧!\n"); cout << "點個贊吧!" << endl; Console.WriteLine("點個贊吧!"); fmt.Println("點個贊吧!"); Response.Write("點個贊吧"); alert(’點個贊吧’)