刷 LeetCode 的大局觀
目前主流的刷題流派有兩種,一種【龜系】,一種【兔系】。
”龜系“刷法的精髓就是每個題目都做乾淨。不滿足於一種解法,各種解法都寫一寫。這種流派適合不太急於準備演算法面試的小夥伴,追求演算法的乾淨優雅。
“兔系“刷法的精髓是暴力,按照標籤來刷,使用固定套路來刷。比如小吳之前分析的那道拍案叫絕的演算法題,如果告訴你是標籤是異或,你馬上能 AC 。這都是套路。
每個標籤內部可以按照 Easy 、Medium、Hard 的順序做,演算法練習是一個系統工程,不要一開始就追求難題,先熟悉熟悉套路,循序漸進的去做,後面所謂的難題也就不在話下。
建議小夥伴第一遍刷題可以使用【兔系】法。
看懂題目
萬事開頭難,看懂題目是做好一道演算法題最開始也是最重要的一步。
我將 LeetCode 上的題大致分為三種型別:
- 考察資料結構,比如連結串列、棧、佇列、雜湊表、圖、Trie、二叉樹等
- 考察基礎演算法,比如深度優先、廣度優先、二分查詢、遞迴等
- 考察基本演算法思想:遞迴、分治、回溯搜尋、貪心、動態規劃等
一些演算法題目會在標題或題目描述中給出明確的題目型別資訊,比如二叉樹的重建、連結串列的反轉。
而有一些題目中則在條件中給予暗示 :
- 設計一個 O(nlogn) 的演算法(分治:在一顆搜尋樹中完成任務,對於資料排序)
- 給定一個有序陣列(二分法)
- 無需考慮額外的空間(用空間換時間上的優化)
- 資料規模大概是 10000(O(n^2)就可以)
- 問題可以被遞迴解決(動態規劃)
無論怎樣,當你拿到一道演算法題的時候,希望你能先去弄明白這道題目要考察的是什麼,是簡單的資料結構還是複雜的演算法思想。
先去理清題目背後解法要用的技術,這樣,這道演算法題目才有做下去的可能。
不要忽視暴力解法
一般來說,BAT 等大廠的演算法面試題基本上都是 Medium 級別及以下,並希望面試者能在 20 分鐘以內給出一個「相對正確」的回答。
為什麼說是 相對正確 ?
每一道演算法題得解法都有很多種,並不是說你沒有給出完美解或者最優解你就是錯的。
“正確” 本身是一個相對概念。
在演算法面試或者平時的演算法練習時,如果沒有頭緒,可以嘗試使用暴力解法。
(不要忽視暴力解法。暴力解法通常是思考的起點。)
當你使用了暴力解法之後,可以與面試官進行溝通優化,把這個過程看作是和麵試官一起探討一個問題的解決方案的過程,這也可以讓面試官瞭解你的思考問題的方式。這也是一個“正確”的回答方式。
先實現功能再去優化。
Done is better than perfect 。
實際編寫
到這一步就是演算法的落地了:將上面的思考結果思路轉換為程式碼。
在編寫的過程中需要注意題目中的邊界條件,比如陣列是否為空,指標是否為 NULL;同時也要注意程式碼的規範性:變數名,模組化,複用性。
做好總結
一定要做好總結,特別是當沒有解出題來,沒有思路的時候,一定要通過結束階段的總結來反思犯了什麼錯誤。解出來了也一定要總結題目的特點,題目中哪些要素是解出該題的關鍵。不做總結的話,花掉的時間所得到的收穫通常只有 50% 左右。
在題目完成後,要特別注意總結此題最後是歸納到哪種型別中,它在這種型別中的獨特之處是什麼。經過總結,這樣題目才會變成你在此問題域中的積累。
做好總結,讓每道題都有最大的收穫。一個月之後自己的狀態應該會有很大變化。
最後,承認刷 LeetCode 很吃力很正常
你我都是普通的程式設計師,不像那些玩 ACM,拳打 LeetCode,腳踩劍指 offer,我們得接受現實:刷題,就是很痛苦很打擊的過程。
但,一遍一遍的刷,多刷一題就多掌握一題,你總會比別人更強一點。
大家一起加油:)