本人今年應屆剛入職杭州某IT企業,日常工作中深感自身算法和代碼能力薄弱,之前找工作雖然也刷過leetcode,但找到工作後並沒有堅持下來,因此想開個刷題專欄監督自己,希望能夠提升自身coding能力~ 如有錯誤或者更優解法,還請評論指出~
本文爲刷題前在網上尋覓的刷題計劃及分類總結,覺得非常有用,打算按照題目tag來刷,先刷每個tag中的easy和medium題。
本文參考博客園的“fish1996”大佬寫的博客,感謝大佬的分類總結。因爲本人喜愛markdown的風格,因此將其改寫成了markdown格式,以便進行檢索,後續根據刷題進程不斷細分類別,希望能夠對大家有所幫助。
【數組操作】
1 https://leetcode-cn.com/problems/two-sum/
初始化1個hashmap,一次遍歷即可完成。判斷target - nums[i]是否在hashmap中,如果在就返回結果,如果不在就將nums[i]插入到hashmap中。
26 https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/
單指針法/雙指針法進行數組去除重複元素
35 https://leetcode-cn.com/problems/search-insert-position/
經典二分法,需要注意邊界條件
【滑動窗口】
3 https://leetcode.com/problems/longest-substring-without-repeating-characters/
維護一個不含重複字符的滑動窗口。需要記錄每個字符最後出現的位置,當遇到重複字符的時候,就把窗口首部調到上一次出現這個字符的下一個位置。
76 https://leetcode.com/problems/minimum-window-substring/
滑動窗口題。維護一個包含t中所有字符的最小滑動窗口,首先用一個hashmap記錄所有t中的字符和出現次數,在s中每遇到一次計數器加一,找到了符合條件的窗口後,嘗試向右移動窗口左指針,直到恰好能夠滿足條件爲止。更新當前最小滑動窗口。
209 https://leetcode.com/problems/minimum-size-subarray-sum/
維護一個大於等於sum的最小滑動窗口。
239 https://leetcode.com/problems/sliding-window-maximum/
求滑動窗口中的最大值。(1) 使用ordered_map,動態更新,取首元素, NlogK。(2) 維護一個指向最大值的指針,當指針不再在窗口內時,向後移動這一指針到合適的位置。最壞時間複雜度是O(NK),但均攤表現比1還要好。(3)使用單調隊列,維護單調遞減的隊列,隊首不再在窗口內時彈出隊首,有更大的元素彈出隊尾。當前最大元素爲隊尾元素。接近O(N)。
424 https://leetcode.com/problems/longest-repeating-character-replacement/
維護一個最多包含k個額外字符的滑動窗口。需要記錄當前出現次數最多字符的出現次數來判斷窗口是否合法,如果超過了,就把首指針向後挪一位,同時更新最多出現次數。對每個合法窗口,取其中的最大值。
438 https://leetcode.com/problems/find-all-anagrams-in-a-string
主要思路是維護兩個hashmap,一個記錄期望出現的字符,一個記錄當前出現的字符。當前出現的字符隨着窗口滾動不停更新,每次移動窗口後,都判斷當前窗口是否滿足條件。同時維護一個滿足條件的count變量,通過比較當前出現字符和期望出現字符的個數來更新,當count等於期望字符串的長度時,意味着當前窗口滿足條件。
480 https://leetcode.com/problems/sliding-window-median/
求滑動窗口的中位值。可以維護一個mutilmap。
576 https://leetcode.com/problems/permutation-in-string/
同438。
904 https://leetcode.com/problems/fruit-into-baskets/
查找最多出現k個字符的最大滑動窗口。可以維護一個包含所有字符出現最後下標的哈希表,每次查到數字超過k個,就把begin指針移到最小的最後出現下標的下一個。
978 https://leetcode.com/problems/longest-turbulent-subarray/
檢查前後兩個數字是否滿足大於或者小於的關係,如果滿足計數器加一,否則清空。掃描兩次處理奇數偶數情況。
992 https://leetcode.com/problems/subarrays-with-k-different-intergers
計算滑動窗口中恰好出現k個不同字符的窗口數目。這道題的一個可以通過的暴力算法是n2的,找到一個滿足條件的滑動窗口後,把begin指針後移,直到不到滿足爲止。統計出現個數。我們需要維護一個可以快速找到k個數字中,最後出現位置最早的那個數字出現的位置,使我們能夠快速移動begin指針。
1004 https://leetcode.com/problems/max-consecutive-ones-iii/
維護最多包含k個0的滑動窗口,一旦超過了k個0,把隊首的0 pop出來。不斷更新當前滑動窗口中的數據個數,並取最大值返回即可。
【排列】
31 https://leetcode.com/problems/next-permutation/
找到下一個排列數。從右到左找到第一個nums[ i ] < nums[ i + 1]的pair,然後在後面找到比nums[ i ] 大的最小數字,把它交換過來。i 之後的數字也一一交換。
46 https://leetcode.com/problems/permutations/
輸出所有排列數。遞歸中,最快的方法是直接交換,實際上執行的是選擇操作,選擇了一個數據後,把它交換到前面;可以保證下一次選擇不會包含着一數字,並且數字被選擇的概率都是相等的。
47 https://leetcode.com/problems/permutations-ii/
輸出所有的排列數(帶重複)。在選擇的時候,使用hashmap記錄在位置i處選過的數據,避免選擇了重複的數據。
60 https://leetcode.com/problems/permutation-sequence
求第k個排列數。數學解法,可以找一下規律。比如對於1234的排列數,一共有24種。我們從左到右依次決定排列數是哪些。首先第一個數有4種可選的,一共有24種,那麼每種就是6個,我們用 k / 6,看它落在哪個區間,就取哪個數字。
之後,還有三個數可選,因爲一共有6種,所以每種有2個,我們計算k / 2……以此類推得到所有位的數字。因爲k從0計數算起來更簡單,所以我們一開始做k–。
996 https://leetcode.com/problems/number-of-squareful-arrays/
這道題要求找到滿足條件的排列數個數。可以在生成排列數的同時檢查是否滿足條件。
【動態規劃】
求最大面積的:題號85(最大面積矩形) 221(最大面積正方形) 1139(最大面積邊框正方形)
5 https://leetcode.com/problems/longest-palindromic-substring/
爬臺階類型問題。考慮字符串的中心字符會更加方便,爲了處理奇數和偶數,可以開成2 * n - 1的dp。或者直接從中心往兩邊擴展,查找最長的。
10 https://leetcode.com/problems/regular-expression-matching/
匹配類型問題。狀態方程稍微有些麻煩,如果當前匹配(包括.匹配),則從i - 1, j - 1轉換到i ,j ,但如果當前匹配爲 ,因爲可代表匹配0個,可選擇匹配或不匹配。
32 https://leetcode.com/problems/longest-valid-parentheses/
最長子串類型問題。
44 https://leetcode.com/problems/wildcard-matching/
匹配類型問題。
62 https://leetcode.com/problems/unique-paths/
爬臺階類型問題。從上方或左方彙總結果。
63 https://leetcode.com/problems/unique-paths-ii
爬臺階類型問題。從上方或左方彙總結果,有障礙則不彙總。
64 https://leetcode.com/problems/minimum-path-sum/
爬臺階類型問題。從上方或左方疊加最小值。
72 https://leetcode.com/problems/edit-distance/
爬臺階類型問題(2D)。要麼選擇替換,要麼選擇添加一個,選擇其中轉換次數最小的。
85 https://leetcode.com/problems/maximal-rectangle/
最大面積問題。先計算每一列的前綴和,可以把每一行看作橫座標,當前的值看作高度,得到一個直方圖一樣的東西,接下來只需計算直方圖中的最大矩形面積。時間複雜度O(N3),用單調棧做是O(N2)
87 https://leetcode.com/problems/scramble-string/
記憶化搜索。在所有可能的交換結果中找是否存在滿足條件的。
91 https://leetcode.com/problems/decode-ways
爬臺階類型問題。當前要麼解析一個字節,要麼解析兩個字節。
95 https://leetcode.com/problems/unique-binary-search-trees-ii/
記憶化搜索。權值在(i, j) 之間的樹可以存起來,作爲更大的樹的子樹。
96 https://leetcode.com/problems/unique-binary-search-trees-ii/
爬臺階類型問題。同上,但無需存儲所有結果了。從左右子樹彙總結果。
97 https://leetcode.com/problems/interleaving-string/
匹配類型問題。需從多種選擇中找到滿足條件的。
115 https://leetcode.com/problems/distinct-subsequences/
匹配類型問題。
120: https://leetcode.com/problems/triangle/
爬臺階類型問題。相當於帶權重的一次爬臺階。
123 https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/
分治。分成兩部分,疊加兩邊最大的結果。
132 https://leetcode.com/problems/palindrome-partitioning-ii/
劃分類型問題。先計算出所有可能的迴文串,dp[ i ] 代表前 i 個字符的最小劃分,找到以 i 結尾的所有迴文串,取劃分最小的那個作爲結果。
139 https://leetcode.com/problems/word-break/
劃分類型問題。
140 https://leetcode.com/problems/word-break-ii
劃分類型問題。和139差不多,但是有些test case 實在太煩人了。
152 https://leetcode.com/problems/maximum-product-subarray
多狀態轉換類型問題。需要維護當前的最大值和最小值,在兩者之間因爲正負數可以發生轉換。
174 https://leetcode.com/problems/dungeon-game/
爬臺階類型問題。但是需要從終點到起點反向求解,才能得到合法的遞推關係,記錄的是到達當前位置需要的hp。
188 https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/
多狀態轉換類型問題(帶次數限制)。存在手上持有股票和手上不持有股票狀態,多了一個最大k次交易的限制條件,因爲在狀態轉移方程中,需要多考慮一個k的維度。
213 https://leetcode.com/problems/dungeon-game/
多狀態轉換類型問題。需要考慮當前偷,當前不偷,第一次偷了,第一次沒偷。
221 https://leetcode.com/problems/maximal-square/
最大面積問題。看三個重疊的正方形加上當前位置能否湊成更大的正方形。
264 https://leetcode.com/problems/ugly-number-ii/
數字類問題。大的醜數是小的醜數乘以2,3,5得到的,每次選擇最小的作爲下一個。
279 https://leetcode.com/problems/perfect-squares
數字類問題。查找當前數字減去一個平方數對應的最小拆分次數。
300 https://leetcode.com/problems/longest-increasing-subsequence/
最長子序列問題。經典dp。
304 https://leetcode.com/problems/range-sum-query-2d-immutable/
最大面積問題。類似221。
309 https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/
多狀態轉換類型問題。持有股票狀態,賣出股票狀態,冷卻狀態。
312 https://leetcode.com/problems/burst-balloons
區間題。需要考慮每個區間的長度,從小往大更新。
313 https://leetcode.com/problems/super-ugly-number/
數字類問題。同264。
321 https://leetcode.com/problems/create-maximum-number
分治。左最大 + 右最大的組合中挑一個最大的。
322 https://leetcode.com/problems/coin-change/
揹包類型問題。總金額爲揹包容量,記錄每個金額的最小次數。
338 https://leetcode.com/problems/counting-bits
數字類型問題。簡單dp。
343 https://leetcode.com/problems/integer-break/
數字類型問題。乘積取最大的。
354 https://leetcode.com/problems/russian-doll-envelopes/
最大子序列問題。二分法做速度會更快。
357 https://leetcode.com/problems/count-numbers-with-unique-digits
數字類型問題。
363 https://leetcode.com/problems/max-sum-of-rectangle-no-larger-than-k
最大面積問題。同時用到了二分,思考這道題可以先從數組入手,再擴展到矩陣。
368 https://leetcode.com/problems/largest-divisible-subset/
最長子序列和問題。不僅需要求出最長的,還需要輸出最長的,所以需要記錄路徑。
375 https://leetcode.com/problems/guess-number-higher-or-lower-ii
分治。在最優解下,取左右最大的 + k。問題描述讓人很困惑,不知道它需要的是最優解下的情況。
416 https://leetcode.com/problems/partition-equal-subset-sum/
揹包類型問題。總和的一半爲揹包總容量,找到能夠恰好填滿揹包的物體。
647 https://leetcode.com/problems/palindromic-substrings/
爬臺階類型問題。迴文子串個數,爲了處理奇偶迴文,可以開一個2 * n + 1長度的dp容器。
650 https://leetcode.com/problems/2-keys-keyboard/
爬臺階類型問題。狀態可由上一個因數轉換過來。
673 https://leetcode.com/problems/number-of-longest-increasing-subsequence/
最長子序列類型問題。需要開兩個數組,在維護最長長度的同時更新最長長度的數量。
714 https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/
多狀態轉換類型問題。存在手上持有股票和手上不持有股票狀態。
740 https://leetcode.com/problems/delete-and-earn/
爬臺階類型問題。根據當前數字和前一數字相差是否爲1決定從前一數字轉換到當前數字,還是從前前一數字轉換到當前數字。
764 https://leetcode.com/submissions/detail/234958158/
計算每個格子四邊最長的1。
801 https://leetcode.com/problems/minimum-swaps-to-make-sequences-increasing/
多狀態轉換問題。交換和不交換兩種。
808 https://leetcode.com/problems/soup-servings
記憶化搜索。直接模擬題意即可,但有一個數學上的trick,並沒有想到。
813 https://leetcode.com/problems/largest-sum-of-averages
劃分類型問題(帶次數限制)。遞推考慮的不只是從前i個數字到前i + 1個數字,還需要考慮從劃分爲k到劃分爲k + 1組,相當於在後面疊加一組。
877 https://leetcode.com/problems/stone-game/
拿左拿右取最大的那種結果。非遞歸寫法是從後往前推導。
931 https://leetcode.com/problems/minimum-falling-path-sum/
爬臺階類型問題。可以從上一層的左中右選擇最小的。
935 https://leetcode.com/problems/knight-dialer
爬臺階類型問題。n + 1長度的從n 長度的累加得到。
956 https://leetcode.com/problems/tallest-billboard
揹包類型問題。要點在於記錄的是兩個揹包的差值。
960 https://leetcode.com/problems/delete-columns-to-make-sorted-iii/
最長子序列類型問題。求n個字符串都符合的最長字典序子序列即可。
983 https://leetcode.com/problems/minimum-cost-for-tickets/
揹包類型問題。一年總天數爲揹包容量。
1024 https://leetcode.com/problems/video-stitching/
揹包類型問題。片段總長度爲揹包容量。
1027 https://leetcode.com/problems/longest-arithmetic-sequence/description/
最長子序列類型問題。之前狀態可存hash中。
1039 https://leetcode.com/problems/minimum-score-triangulation-of-polygon/
記憶化搜索。需要以邊作爲子問題劃分的基礎。
1043 https://leetcode.com/problems/partition-array-for-maximum-sum/
限制長度的劃分。注意劃分爲k個連續集合,和劃分的連續集合中最多k個數字,以及劃分爲k個可不連續的子集的區別。
1048 https://leetcode.com/problems/longest-string-chain/
爬臺階類型問題。從k - 1長度轉換到k長度,取其中總長最大的。
- https://leetcode.com/problems/filling-bookcase-shelves/
揹包類型問題(2D)。當前書可以單獨放,也可以選擇和前面n本一起放。
1139 https://leetcode.com/problems/largest-1-bordered-square
最大面積問題。類似85,由於是邊框問題,要同時考慮橫向累積和縱向累積,而85只需考慮其中一個就夠了。
1143 https://leetcode.com/problems/longest-common-subsequence/
最長公共子序列。經典dp。
1155 https://leetcode.com/problems/number-of-dice-rolls-with-target-sum/
揹包類型問題。帶次數限制,可多次使用的完全揹包。
【區間重疊】
56 https://leetcode.com/problems/merge-intervals/
先排序,再逐個檢查當前區間能否和結果隊列中最後一個區間合併。
57 https://leetcode.com/problems/insert-interval/
先把在新區間之前的都加入結果,和新區間存在重疊的取最大最小作爲邊界,在新區間之後的都加入結果。
435 https://leetcode.com/problems/non-overlapping-intervals/
先排序,一旦檢測到重疊,移除end位置比較大的元素。
452 https://leetcode.com/problems/minimum-number-of-arrows-to-burst-balloons/
維護一個當前最小的重疊區域,如果新的區間和這個區間重疊,那麼縮小這個區間,否則重置。每重置一次計數加一。
【字典樹】
208 https://leetcode.com/problems/implement-trie-prefix-tree/
實現字典樹。包含查詢單詞,和查詢單詞是否包含前綴。
【寬度優先搜索】
在求單源最短路徑中,我們可能會遇到兩種情況,一種是無權的最短路徑,另一種是有權的最短路徑。
對於無權的最短路徑,因爲我們是按層訪問的,所以我們只需要跟蹤當前搜索層數;一旦我們訪問到了某個結點,那麼當前的層數就一定是到達它的最短路徑。
而對於有權的最短路徑,我們往往採取貪心的策略,在已經確定了最短路徑的結點中,選擇它們相鄰的未訪問過的結點的最小權重路徑,加入訪問結點集合中。
在有權的情況下,我們常常會用到一個dist容器,用於存儲出發點到當前點的最短路徑,並且在發現了更短的路徑後,需要更新dist裏的數據,這是考慮到以下情況:
當我們訪問到藍色結點時,我們會同時更新它的鄰居的最短距離,比如將橙色結點更新爲dist[blue] + 8; 但是此時我們只是確定了藍色結點的路徑是最短的,還無法保證橙色結點的路徑是最短的;因此需要在綠色結點訪問到橙色結點時,更新橙色結點的最短路徑。
102 https://leetcode.com/problems/binary-tree-level-order-traversal/
樹的層次遍歷。基礎題。
126 https://leetcode.com/problems/word-ladder-ii/
單源無權最短路徑。難點在於要記錄所有的路徑。我的做法是先用寬搜得到最短路徑的鄰接關係,之後再利用深搜從後往前歸納所有路徑,然後把路徑倒序。
127 https://leetcode.com/problems/word-ladder/submissions/
單源無權最短路徑。
207 https://leetcode.com/problems/course-schedule/
拓撲排序。計算所有點入度,入度爲0的點放入隊列。每pop一個節點,它的鄰居入度都減一,如果出現了入度爲0的點,再放入隊列。如果訪問的節點數等於課程數,那麼可以完成所有課程。
301 https://leetcode.com/problems/remove-invalid-parentheses/
搜索所有可能的去除組合,判斷是否是有效括號,如果是就加入結果。
310 https://leetcode.com/problems/minimum-height-trees/
類拓撲排序。找到只有一個鄰居的點加入隊列,每pop一個節點,它的鄰居的鄰接表就減去這一節點,直到只剩下一/兩個節點。
513 https://leetcode.com/problems/find-bottom-left-tree-value/
樹的層次遍歷。深搜應該也可以的。
515 https://leetcode.com/problems/find-largest-value-in-each-tree-row/
樹的層次遍歷。
542 https://leetcode.com/problems/01-matrix/
多源無權最短路徑。和單源相比,也就是把所有的0加入起始隊列就可以了。
743 https://leetcode.com/problems/network-delay-time/
單源有權最短路徑。相當於求到每個點的最短路徑,然後去其中最大值。
752 https://leetcode.com/problems/open-the-lock/
單源無權最短路徑。把鎖的狀態記錄爲字符串即可。
773 https://leetcode.com/problems/sliding-puzzle/
單源無權最短路徑。特別的時需要用字符串來記錄所有狀態量,找到目標狀態量後就退出,我們總能保證找到時用到的步數是最少的。
778 https://leetcode.com/problems/swim-in-rising-water/
寬度優先搜索。使用優先隊列,每次選擇值最小的作爲下一個,並更新最大值作爲結果。
787 https://leetcode.com/problems/cheapest-flights-within-k-stops/
單源有權最短路徑。由於有k的次數限制,用寬搜會更加直觀。記錄當前到達終點的最短路徑,如果有更短的,把新的節點加入隊列。
847 https://leetcode.com/problems/shortest-path-visiting-all-nodes/
單源無權最短路徑(帶狀態)。判斷重複節點訪問需要考慮當前狀態:訪問過哪些節點。
854 https://leetcode.com/problems/k-similar-strings/
寬度優先搜索。每次匹配一個字符,第K次後退出。
863 https://leetcode.com/problems/all-nodes-distance-k-in-binary-tree/
先從樹建圖,然後做層次遍歷。
864 https://leetcode.com/problems/shortest-path-to-get-all-keys/
單源無權最短路徑(帶狀態)。判斷重複節點訪問需要考慮當前狀態:帶了幾把鑰匙。
909 https://leetcode.com/problems/snakes-and-ladders/
單源無權最短路徑。比較麻煩的一點是要換算位置和對應數字,此外要特殊處理梯子,因爲遇到了梯子/蛇一定要滑過去,所以我們可以當作把這一位置作爲跳板直接到達了梯子末端,就好像沒有來過這一位置一樣。
934 https://leetcode.com/problems/shortest-bridge/
多源無權最短路徑。先用深搜給一個島嶼加上標記,之後的做法就類似於542了,取最小的最短路徑即可。
1091 https://leetcode.com/problems/shortest-path-in-binary-matrix/
單源無權最短路徑。
1129 https://leetcode.com/problems/shortest-path-with-alternating-colors/
單源無權最短路徑,但有限制條件。這道題要求每次走不同顏色的路徑,需要注意的是不同顏色路徑到同一個結點的訪問狀態需要分別維護。
1135 https://leetcode.com/contest/biweekly-contest-5/problems/connecting-cities-with-minimum-cost/
最小生成樹。使用優先隊列, 從一個空集合開始,加入任一頂點,並找到該集合中頂點連接的權重最小的邊,把該邊連接的點也加入集合。直到所有的點都加入了集合,意味着找到了最小生成樹。
1136 https://leetcode.com/contest/biweekly-contest-5/problems/parallel-courses/
拓撲排序。
(1) 對於有向圖,記錄所有頂點的入度(指向該頂點的邊的個數)
(2) 找到所有入度爲0的頂點,把頂點放入隊列
(3) 從隊列pop出一個元素,該頂點則是當前滿足條件的頂點,可將計數加一,並把它指向的頂點的入度都減一,重複(2)(3)直到隊列爲空
(4)如果已經找不到入度爲0的頂點,而當前計數還沒有覆蓋到所有頂點,那麼說明有向圖中可能出現了環路。
【深度優先搜索】
17 https://leetcode.com/problems/letter-combinations-of-a-phone-number/
暴力搜索所有可能的電話號碼組合。
22 https://leetcode.com/problems/generate-parentheses
暴力搜索所有可能的括號組合。需要傳入當前需要的’(‘和’)'數量。
37 https://leetcode.com/problems/sudoku-solver/
暴力搜索可能的解。發現無法繼續時就回退到上一步。
39 https://leetcode.com/problems/combination-sum/
暴力搜索所有可能的等於sum的組合。爲了避免生成重複,先進行排序,按照非遞減的順序找下一個數字。
40 https://leetcode.com/problems/combination-sum-ii/
暴力搜索所有可能的等於sum的組合。和39相比存在重複,選擇的時候跳過重複即可。
51 https://leetcode.com/problems/n-queens/
回溯。
52 https://leetcode.com/problems/n-queens-ii/
回溯。
90 https://leetcode.com/problems/subsets-ii
暴力搜索所有可能的集合結果。
113 https://leetcode.com/problems/path-sum-ii/
暴力搜索所有可能的等於sum的組合。
133 https://leetcode.com/problems/clone-graph/
遞歸拷貝。如果已經拷貝過,就直接設置指針,沒有拷貝過,就去拷貝。
200 https://leetcode.com/problems/number-of-islands/
每搜索一趟就能遍歷一個島嶼,搜索後加上visit標記,一共搜了幾次就有幾個島嶼。
241 https://leetcode.com/problems/different-ways-to-add-parentheses/
分治。先記錄左邊運算結果,再計算右邊運算結果,最後把兩個結果合併起來。
698 https://leetcode.com/problems/partition-to-k-equal-sum-subsets/
記憶化搜索。首先求出劃分爲k份後每個集合的總和目標值,每次取一個沒有訪問過的數據作爲下一個累加數據,每找到一個目標值後份數減一,目標值重置爲0。看能否恰好減爲0。
417 https://leetcode.com/problems/pacific-atlantic-water-flow/
記憶化搜索。返回值是pair對,記錄當前位置能否到達兩個海洋,如果它能到達的位置能到達海洋,那麼它也能到達。最後掃一遍所有數據,找到兩個都爲true的加入結果。
529 https://leetcode.com/problems/minesweeper/
搜索遍歷。每次掃描到某個空白節點後都判斷它能夠被填充,不能則返回,能則繼續搜索,並修改指向內容,作爲visit訪問標記。
785 https://leetcode.com/problems/is-graph-bipartite/
二分圖判斷。給每個節點染色,並且檢查它的鄰居和它的顏色是否相等,如果存在相等說明不是二分圖。
851 https://leetcode.com/problems/loud-and-rich/
建立有向圖,搜索遍歷所有比它富有的人,取其中最安靜的。
967 https://leetcode.com/problems/numbers-with-same-consecutive-differences/
搜索所有滿足條件的結果。
1034 https://leetcode.com/problems/coloring-a-border/
深度優先搜索。先全塗一個色,然後對邊界和非邊界分別塗色。
【棧】
42 https://leetcode.com/problems/trapping-rain-water/
維護遞減的單調棧。遇到大於棧頂的,就pop,因爲當前棧頂元素左右兩邊的高度都一定比它高,所以可以同時計算它(橫向的)蓄水量。
84 https://leetcode.com/problems/largest-rectangle-in-histogram
維護遞增的單調棧,當發現當前數字比棧頂要小的時候,此時棧頂元素是最大的(大於棧裏的下一個元素,也大於當前元素),所以可以計算以當前棧頂元素爲高的矩形面積,並比較是不是最大的。
150 https://leetcode.com/problems/evaluate-reverse-polish-notation/
棧模擬遞歸。遇到運算符就pop兩個數字進行計算,並把結果push進去。
316 https://leetcode.com/problems/remove-duplicate-letters/
維護遞增的單調棧。首先,統計每個數字出現的次數,每次訪問過就把出現次數減一。遞增的單調棧對應着最小字典序的結果,已經在棧中的加一個visit標記,避免重複入棧,如果遇到比棧頂更小的,並且棧頂對應的字符在後面也有出現,可以考慮之後再入棧這一字符。所以可以把棧頂pop出來,替換爲新的字符,並更新visit標記。
331 https://leetcode.com/problems/verify-preorder-serialization-of-a-binary-tree/
棧模擬遞歸。這道題需要記錄一個count值,表示當前樹還有多少個地方可以插入新的節點(包括插入數字和插入Null)。如果插入的是數字節點,那麼會多一個可用的位置(新的節點佔用了一個,但又新增了兩個);如果插入的是null,那麼它只會佔用一個,所以會少一個可用的位置。每次遇到沒有可用位置的時候,意味着當前字符串非法。掃描到最後時,如果可用位置還有剩餘,也意味着當前字符串非法。
341 https://leetcode.com/problems/flatten-nested-list-iterator/
棧模擬遞歸。先把所有數據逆序入棧,如果棧頂是數字就直接返回,如果棧頂是鏈表,把鏈表所有值逆序入棧,然後pop當前數據,再循環檢查棧頂是否爲數字。
385 https://leetcode.com/problems/mini-parser/
棧模擬遞歸。解析括號,直接使用遞歸解析更加簡單。
402 https://leetcode.com/problems/remove-k-digits
維護遞增的單調棧。出現了比棧頂小的,就可以移除棧頂的元素,此時k減去1。
456 https://leetcode.com/problems/132-pattern/
維護遞減的單調棧。從後往前遍歷,相當於尋找231paterrn。遇到更大的數就pop出來,同時記錄棧頂的值(作爲第二大的數),之後判斷接下來的值小於這個第二大的數即可。
503 https://leetcode.com/problems/next-greater-element-ii/
維護遞減的單調棧。不過由於題目要求是循環的,需要兩個pass,第二個pass處理循環生效的next greater,同時需要把下標已經超出範圍的隊首數據及時pop出來。
739 https://leetcode.com/problems/daily-temperatures/
維護遞減的單調棧。因爲要找到比它高的第一個溫度,所以遇到遞減的都緩存起來,等到有更高的再一次性更新。
1019 https://leetcode.com/problems/next-greater-node-in-linked-list/
維護遞減的單調棧。這道題對象是鏈表,不像數組可以快速通過下標索引,所以比較方便的做法是在棧中同時記錄數字和對應的下標,並且默認填0,如果找到了比它大的第一個數,再修改下標對應的數字。
【二分搜索】
4 https://leetcode.com/problems/median-of-two-sorted-arrays/
雙指針二分問題。把兩個數組x,y劃分爲兩個大小相等(或差1)的集合,維護數據maxLeft, minRight,哪邊不滿足maxLeft < minRight就移動一下指針。
11 https://leetcode.com/problems/container-with-most-water/
雙指針二分問題。指針記錄首尾位置,哪邊更矮哪邊的指針向中間移動,同時更新最大容水面積。
15 https://leetcode.com/problems/3sum/
雙指針二分問題。
16 https://leetcode.com/problems/3sum-closest/
雙指針二分問題。對於排好序的數組,首先確定三個數位置在中間的那個數字,然後在它左右搜索另外兩個數,如果大於目標,則右指針左移,否則左指針右移。
18 https://leetcode.com/problems/4sum/
雙指針二分問題。和3sum相比,要先選定兩個數,而不是一個數。
33 https://leetcode.com/problems/search-in-rotated-sorted-array/
根據下標二分問題。檢查二分後的半段是否滿足遞增條件,如果滿足且數據落在這一區間,就在這一區間查找,否則到另一區間查找。
34 https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/
根據下標二分問題。要點是改變low或high的時候把當前數字mid也包含進來,因爲它也可能是結果。
35 https://leetcode-cn.com/problems/search-insert-position/
74 https://leetcode.com/problems/search-a-2d-matrix/
根據下標二分問題。
162 https://leetcode.com/problems/find-peak-element/
根據下標二分問題。每次檢查mid左右兩個數和mid的關係,再決定如何進行下一步。
250 https://leetcode.com/problems/search-a-2d-matrix-ii
雙指針二分問題。從矩陣的右上角開始搜索,到下標越界後退出。
315 https://leetcode.com/problems/count-of-smaller-numbers-after-self/
先額外存一個排序好的數組。然後查找lower_bound,看有多少個數比它小,並把這個數從排序數組中移除。
475 https://leetcode.com/problems/heaters/
二分查找上下界問題。對加熱器進行排序,通過二分查找距離最近的熱水器,並求所有最近距離的最大值。
528 https://leetcode.com/problems/random-pick-with-weight/
二分查找上下界問題。首先計算一個累積的頻數,根據總頻數來進行隨機,之後通過二分查找得到當前隨機數對應的下標。
704 https://leetcode.com/problems/binary-search/
標準二分查找
875 https://leetcode.com/problems/koko-eating-bananas/
二分猜答案問題。也就是在一定的求解空間中找到最小滿足條件的值,使得KoKo能夠以最慢的速度在特定時間內吃完所有香蕉。
911 https://leetcode.com/problems/online-election/
二分查找上下界問題。主要是根據時間來二分,先預先計算好當前時間點對應的選舉人,存到hashmap中。之後通過二分找到時間,再通過hash找到對應選舉人。
1011 https://leetcode.com/problems/capacity-to-ship-packages-within-d-days/
二分猜答案問題。也就是在一定的求解空間中找到最小滿足條件的值,使得貨船能夠以最小的容量在特定時間內運完所有貨物。
1146 https://leetcode.com/problems/snapshot-array/
二分查找上下界問題。每次修改值的時候記錄一下當前快照的值,然後每次查找當前下標特定快照id時的值時,二分查找小於等於這一快照id對應的值即可。
【哈希】(19)
30 https://leetcode.com/problems/substring-with-concatenation-of-all-words/
用hash記錄目標值,從每個下標開始搜索當前字符串是否滿足條件,滿足則加入結果。
36 https://leetcode.com/problems/valid-sudoku/
哈希檢測重複。
49 https://leetcode.com/problems/group-anagrams/
所有的字符串hash到字典序。
347 https://leetcode.com/problems/top-k-frequent-elements/
維護每個數字出現頻率,每個頻率對應數字,然後從高頻率往低搜索。
467 https://leetcode.com/problems/unique-substrings-in-wraparound-string/
哈希計數。遇到特定值的時候就添對應容器加計數,最後把所有計數累加起來得到結果。
523
同560類型題。
560 https://leetcode.com/problems/subarray-sum-equals-k/
使用哈希表記錄之前出現的前綴和sum - k。
781 https://leetcode.com/problems/rabbits-in-forest/
值爲n的可以和其它n + 1個值爲n的成組,統計每個值出現的次數,看它們可以組成多少組相同顏色的兔子,然後乘以組中兔子個數。
890 https://leetcode.com/problems/find-and-replace-pattern/
維護兩個哈希,a中第i位數字和b中第i位數字相互映射,檢測之後的相同數字是否也滿足這種映射。
895 https://leetcode.com/problems/maximum-frequency-stack/
維護兩個哈希。一個哈希記錄每個數字出現的頻率,一個哈希記錄每個頻率出現的數字,因爲可能有多個,可存入棧中。每次取最大頻率對應的棧頂值,並移除。如果最大頻率變爲0,那麼移除這一頻率。
930 https://leetcode.com/problems/binary-subarrays-with-sum/
記錄連續0出現的數字,計算所有(zeros[i] + 1) * (zeros[i + S] + 1)的累加。
954 https://leetcode.com/problems/array-of-doubled-pairs
記錄每個數字出現頻率。按絕對值排序,對於每個數字,查找是否存在2 * x的數字,如果存在,就把它移除,否則返回false。
974 https://leetcode.com/problems/subarray-sums-divisible-by-k/
使用hash記錄當前前綴和%K,如果前面存在相同的數字,那麼意味着存在這樣的連續子數組。
981 https://leetcode.com/problems/time-based-key-value-store/
維護unordered_map<int,map<int,int>>的結果,二分查找每個key對應的時間戳。
1044 https://leetcode.com/problems/longest-duplicate-substring/
哈希字符串匹配。先二分,再哈希查找是否存在長度爲k的重複字符串。
1072 https://leetcode.com/problems/flip-columns-for-maximum-number-of-equal-rows/
假設當前行是結果。查找和它相等,以及和它恰好相反的子串數量,取最大值。
1074 https://leetcode.com/problems/number-of-submatrices-that-sum-to-target/
對任何兩行/列的前綴和,求子數組的前綴和。
1124 https://leetcode.com/problems/longest-well-performing-interval/
等價於找和大於0的最長區間。
1138 https://leetcode.com/problems/alphabet-board-path/
哈希記錄每個字母的下標。按照曼哈頓距離挪過去。
【堆】
23 https://leetcode.com/problems/merge-k-sorted-lists/
把所有數據加入堆裏,再pop出來構建新鏈表。
215 https://leetcode.com/problems/kth-largest-element-in-an-array/
維護最大爲K的堆。時間複雜度O(NlogK)。
692 https://leetcode.com/problems/top-k-frequent-words/
維護最大爲K的堆。
793 https://leetcode.com/problems/k-closest-points-to-origin/
維護最大爲K的堆。
1383 https://leetcode.com/problems/maximum-performance-of-a-team/
維護最大爲K的堆。這裏首先將所有人按照效率排序,優先選高效的,然後逐步剔除速度慢的人。
【並查集】
128 https://leetcode.com/problems/longest-consecutive-sequence/
把相鄰元素合併到一個集合中,取數量最大的那個集合作爲結果。哈希的做法是先把所有值放到哈希裏,對每個值查找n+1和n-1的值有哪些,記錄兩端長度。找到了從哈希表中移除。
684 https://leetcode.com/problems/redundant-connection/
類似於最小生成樹。每遇到一對節點把它們Union一下,如果已經在一個集合了,就返回這對邊,說明是要被去掉的。
924 https://leetcode.com/problems/minimize-malware-spread
優先去除所在集合只包含它一個初始節點的初始節點,如果有多個這樣的節點,取集合較大的。如果集合大小一樣,或者該集合包含了多個初始節點,取下標最小的。
【貪心】(10)
45 https://leetcode.com/problems/jump-game-ii/submissions/
可以使用搜索完成。但標準做法是貪心,從當前位置跳到下一個位置時,選擇下一個能跳到最遠位置的地方。
55 https://leetcode.com/problems/jump-game/
暴力算法是n2。貪心思想是從後往前查詢能跳到當前位置的,如果找到了,更新當前位置。最終位置如果能到0就返回true。
134 https://leetcode.com/problems/gas-station
如果A->B無法完成到達,那麼中間也沒有答案(之前累積的結果都是正的,最後一個位置讓它不再爲正數;如果把起始指針向後移動,情況只會更糟);如果氣體總和大於消耗量,那麼必然有解。
378 https://leetcode.com/problems/monotone-increasing-digits/
從後往前遍歷,找到最後一個i + 1小於i的pair,之後的數字都設置爲9,找到小於的時候,把上一個數字減一。
630 https://leetcode.com/problems/course-schedule-iii/
按照結束時間排序,如果當前課程無法在ddl前完成了,就去掉一個時間最長的課程。貪心的標準做法是按結束時間排序後儘可能選,選不了的就放棄。但是這道題的區別在於它的開始時間並不是確定的。
789 https://leetcode.com/problems/escape-the-ghosts/
如果能和鬼在終點相遇,那麼也會在其他地方相遇。
870 https://leetcode.com/problems/advantage-shuffle/
In ordered to maximize the advantage of array A with respect to B, we had better choose the smallest element in array A that is larger than the element in B. After each selection, we erase the data we choose in A to avoid repetition.
948 https://leetcode.com/problems/bag-of-tokens/
排序。從左邊消耗,能量不夠了從右邊取,直到無法補充能量,或首尾指針相遇。
955 https://leetcode.com/problems/delete-columns-to-make-sorted-ii/
從左到右掃描,如果有一個數字不滿足字典序,那麼刪掉該列,否則保留。
1147 https://leetcode.com/problems/longest-chunked-palindrome-decomposition/
左邊右邊開始依次匹配,匹配到了就加一。
【樹】
94 https://leetcode.com/problems/binary-tree-inorder-traversal/
樹的中序遍歷。非遞歸的做法是使用棧,先入棧所有左子樹,pop出來的時候入棧當前節點的右子樹的所有左子樹。
98 https://leetcode.com/problems/validate-binary-search-tree
檢查是否是合法二叉搜索樹。對於所有結點,檢查是否滿足大於左子樹,小於右子樹。
105 https://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/
根據中序和前序重建樹。前序第一個作爲根,在中序找到這個數字,左邊的是左子樹,右邊的是右子樹。
144 https://leetcode.com/problems/binary-tree-preorder-traversal/
樹的前序遍歷。非遞歸的做法是使用棧,先入棧右子樹,再入棧左子樹。
145 https://leetcode.com/problems/binary-tree-postorder-traversal/
樹的後序遍歷。非遞歸的做法是使用棧,先入棧左子樹,再入棧右子樹,再把結果反過來。
173 https://leetcode.com/problems/binary-search-tree-iterator/
樹的中序遍歷。查找輸出二叉搜索樹的下一個最大值,相當於使用非遞歸進行中序遍歷。
199 https://leetcode.com/problems/binary-tree-right-side-view/
樹的層次遍歷。輸出每層最後一個結點。
222 https://leetcode.com/problems/count-complete-tree-nodes/
統計完全二叉樹的節點個數。可以先判斷當前子樹是不是滿二叉樹,是的話直接返回2^n - 1,否則遞歸查找。
230 https://leetcode.com/problems/kth-smallest-element-in-a-bst/
中序遍歷,輸出第k個數字。
236 https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/
最小公共祖先。
865 https://leetcode.com/problems/smallest-subtree-with-all-the-deepest-nodes
同1123。
1026 https://leetcode.com/problems/maximum-difference-between-node-and-ancestor/
返回當前節點子節點的最大值和最小值,計算差並更新結果。
1123 https://leetcode.com/problems/lowest-common-ancestor-of-deepest-leaves
最小公共祖先,選擇左右節點中高度比較小的結點對應的答案,如果高度一樣,返回自己。
【鏈表】
2 https://leetcode.com/problems/add-two-numbers/
19 https://leetcode.com/problems/remove-nth-node-from-end-of-list/
傳說中這道題的標準做法是維護兩個指針,讓一個指針先走n步,然後兩個一起動。第一個指針到盡頭了,第二個指針就是要刪的位置。
24 https://leetcode.com/problems/swap-nodes-in-pairs/
記錄了last,cur,next,nnext指針,交換完了一次跳2格
61 https://leetcode.com/problems/rotate-list/
【數學】
一些奇怪的找規律題,也不知道是啥類型,就叫數學吧?= =
6 https://leetcode.com/problems/zigzag-conversion/
類似編碼解碼一樣的zigzag打印。
43 https://leetcode.com/problems/multiply-strings/
字符串計算乘法。
48 https://leetcode.com/problems/rotate-image/
打印旋轉矩陣。
54 https://leetcode.com/problems/spiral-matrix/
打印旋轉矩陣。
223 https://leetcode.com/problems/rectangle-area/
計算矩形面積。
228 https://leetcode.com/problems/summary-ranges/
連續數字打印成特定格式。
537 https://leetcode.com/problems/complex-number-multiplication/
計算複數相加。
885 https://leetcode.com/problems/spiral-matrix-iii/
打印旋轉矩陣。
1104 https://leetcode.com/problems/path-in-zigzag-labelled-binary-tree/
zigzag打印2^n.
【其它】
41 https://leetcode.com/problems/first-missing-positive/
原地排序。把下標對應的數字都交換到下標處。之後再從左到右查到第一個i + 1 != A[i]的元素,即爲答案。
75 https://leetcode.com/problems/sort-colors/
計數排序。
179 https://leetcode.com/problems/largest-number/
排序。將數字轉換爲字符串,比較s1 + s2 和 s2 + s1
229 https://leetcode.com/problems/majority-element-ii/
投票法。3分記兩票。滿足則加一票,爲0則選舉當前,否則都減去一票。
238 https://leetcode.com/submissions/detail/232467850/
計算首尾累積乘積。
287 https://leetcode.com/problems/find-the-duplicate-number/
快慢指針。查找是否存在環。快指針走2步,慢指針走1步,相遇則存在環。設慢指針走了路程s,則快指針走了2s,環長度爲s。若環的起始位置爲d,則慢指針的位置在起始位置過一點的地方,它只要再走d步又可以回到起始位置 。
775 https://leetcode.com/submissions/detail/235207901/
檢查錯位的數字是否都是相鄰的。
807 https://leetcode.com/problems/max-increase-to-keep-city-skyline/
模擬題。
912 https://leetcode.com/problems/sort-an-array/
排序練習。作爲複習,快速排序的做法是:選取一個主元(可取首中尾的中位數,然後把比它小的交換到左邊,比它大的交換到右邊)。每次快排結束,總能保證一個數字被放到了正確位置。
1014 https://leetcode.com/problems/best-sightseeing-pair/
i,j合併同類項,分別求兩個的最大值。