| 1 |
Two Sum |
Easy |
⭐ |
array |
小暖身而已 |
| 3 |
Longest Substring Without Repeating Characters |
Medium |
⭐ ⭐ ⭐ |
string |
可與 #340 Longest Substring with At Most K Distinct Characters 對照。因為本題是要求完全不重複,所以我們的 map 是記 char 出現過的 index,這讓我再發現重複的時候,可以直接調整 window 的 head 到新的位置;但 340 是容許 k 次重複,所以若我們的 map 改記得的是 char 出現的次數,那每當重複次數超過容許值因而要調整 head,就要一步一步調,當然如果 map 是把每個 char 出現的位置都記錄下來,自然也就可以一次調到位。有就是說 340 其實比較有 slide window 的感覺,但本題其實不需要明確有 window 的概念,而是比較像維護一個 valid head 的 index 就可以 |
| 5 |
Longest Palindromic Substring |
Medium |
⭐ ⭐ |
dp string |
不算難,但可以作為 DP 的題目,或者是進階演算法有興趣的可以藉此研究 Manacher’s algorithm |
| 11 |
Container With Most Water |
Medium |
⭐ ⭐ ⭐ |
2pointer |
暴力解很容易,進階解不一定想到到。但只要先以左右兩側為第一個選擇,想辦法去提升容量,演算法就很容易出來 |
| 15 |
3Sum |
Medium |
⭐ ⭐ ⭐ |
array |
暴力解就是 O(n^3),進階解不一定想到到。想有比 O(n^3) 快的方法,掃一次是一定需要的,所以至少有 n,重點在於掃一次取得第一個數後,怎麼挑另外兩個數,並且不能是 O(n^2),所以合理可以想到嘗試先 sort 過,那接下來就會變得跟 #11 Container With Most Water 很像。但另外還有檢查重複的部分也需要一些琢磨 |
| 19 |
Remove Nth Node From End of List |
Medium |
⭐ ⭐ ⭐ |
ll |
暴力解很容易,進階解要想一下,也是個典型 2-pointer 問題。如果對 Rust 有興趣的可以就本題了解一些 Rust 的限制。fast slow 是 2-pointer 問題中常見的技巧 |
| 20 |
Valid Parentheses |
Easy |
⭐ ⭐ ⭐ ⭐ ⭐ |
string |
經典題,很容易,但如果沒有做過還是可能會漏一些東西 |
| 21 |
Merge Two Sorted Lists |
Easy |
⭐ ⭐ ⭐ ⭐ ⭐ |
ll sort |
很容易,但 Python 的 List 太強大,用久了可能會忘了在有限制的單向串列狀況下怎麼處理這個問題。同時這也是一題可以觀察 Rust 語言特性的題目 |
| 23 |
Merge k Sorted Lists |
Hard |
⭐ ⭐ ⭐ ⭐ ⭐ |
ll sort |
其實應該不到 Hard,尤其是如果已經做過 #21 Merge Two Sorted Lists。把 merge 2 個轉換成 merge k 個並沒有額外需要什麼高明想法,唯一可能就是先把他們維持排序好,這樣選下一個的時候就很好選。更高級一點就是用 heap 來維護這些 list 的順序 |
| 33 |
Search in Rotated Sorted Array |
Medium |
⭐ ⭐ ⭐ ⭐ |
search |
需要一點觀察,有可能會走錯方向,另外大於小於其實也有點煩 |
| 39 |
Combination Sum |
Medium |
⭐ ⭐ ⭐ |
sum |
只要注意到數字可以被重複使用,那這題蠻直觀的其實 |
| 48 |
Rotate Image |
Medium |
⭐ ⭐ ⭐ |
2darray |
兩種解法,一種很容易看到眼花,一種要做過才知道 |
| 49 |
Group Anagrams |
Medium |
⭐ ⭐ |
string |
土法煉鋼,沒什麼高深想法,稍有練習不同語言基本語法的作用。字元組成相同,代表每一個 char 使用的次數相同,所以問題就轉變為替每一種樣式創造一個 unique 的 identifier |
| 53 |
Maximum Subarray |
Easy |
⭐ ⭐ ⭐ |
sum |
我覺得這題可能也可以 Medium。會被歸在 Easy 大概是因為 O(n) 解就是很典型的這類 array 題 greedy 的思路,他是一題經典的基本 DP (Dynamic Programming) 題,也就是存在 f(i) = g(f(i-1)) 這樣的特性,本題的 g 就是 max(f(i-1)+nums[i], nums[i])。另外有 O(n log n) 的 divide and conquer 解可能是直觀一點的解,是一個典型的 divide and conquer 範例,所以可能也是另一個歸在 Easy 的原因吧 |
| 54 |
Spiral Matrix |
Medium |
⭐ |
2darray |
就分四組細心處理完就好,沒什麼 |
| 55 |
Jump Game |
Medium |
⭐ ⭐ ⭐ ⭐ |
sum |
培養認出適合用 Greedy 演算法的問題類型,DP (dynamic programming) 和 Greedy 都是算處理本題蠻直觀的想法,但先想到哪一個就有可能導致造盲區而想不到另一個 |
| 56 |
Merge Intervals |
Medium |
⭐ ⭐ ⭐ |
interval |
想出解法容易,但可能會瑣碎,不一定能直接想到最簡潔的解法,讓其變簡潔的關鍵就是要先把 intervals 據其起點做 sort |
| 57 |
Insert Interval |
Medium |
⭐ ⭐ ⭐ |
interval |
隨然說是 #56 Merge Intervals 的延伸,但也不見得就做得出這題 |
| 62 |
Unique Paths |
Medium |
⭐ ⭐ ⭐ |
p&c |
基本排列組合數學題 |
| 70 |
Climbing Stairs |
Easy |
⭐ |
recursive |
recursive 的課本基礎範例 |
| 73 |
Set Matrix Zeroes |
Medium |
⭐ |
2darray |
應該算 Easy,沒什麼特別的… |
| 76 |
Minimum Window Substring |
Hard |
⭐ ⭐ ⭐ |
2pointer |
想法本身是 Medium 等級,因為題目有說要 O(m + n) 的解,這反而成了提示,所以想法本身不難。不過要實作因為有好些細節所以可以到 Hard |
| 79 |
Word Search |
Medium |
⭐ ⭐ ⭐ ⭐ |
2darray dfs |
想法不難,但要成功寫實作出來有可能會卡住 |
| 91 |
Decode Ways |
Medium |
⭐ |
string |
沒什麼特別的,幾乎算 Easy 吧 |
| 98 |
Validate Binary Search Tree |
Medium |
⭐ ⭐ ⭐ ⭐ |
tree dfs bst |
雖然星星多,但只是因為他是演算法基本功,這其實不應該是刷題了才會的東西,所以他應該要歸在 Easy。課本上判斷一個 BST 是否合法的方法就是用 DFS 的 in-order traversal 看數字是否遞增。頂多實作上需要注意的是 recursion 中 return 的效果,如果發現不合法應該就可以直接終止,不用全部走完 |
| 100 |
Same Tree |
Easy |
⭐ ⭐ ⭐ ⭐ |
tree |
就…基本題 |
| 102 |
Binary Tree Level Order Traversal |
Medium |
⭐ ⭐ ⭐ ⭐ |
tree bfs |
BFS order 使用 queue 來 traverse 是基本概念,但他要把同一 level 的都明確搜集在一起,這就需要另外有方法意識到當前的 level,所以歸在 medium |
| 104 |
Maximum Depth of Binary Tree |
Easy |
⭐ ⭐ ⭐ |
tree dfs |
就…基本題 |
| 105 |
Construct Binary Tree from Preorder and Inorder Traversal |
Medium |
⭐ ⭐ ⭐ ⭐ |
tree dfs |
算是經典題吧,解法沒做過不容易想到,要特別記一下 |
| 121 |
Best Time to Buy and Sell Stock |
Easy |
⭐ ⭐ ⭐ ⭐ |
array |
暴力解就是 O(n^2),但再仔細想一下其實走一輪就可以有答案,強迫自己以人類的角度走一輪就要得出答案,演算法自然就出來了 |
| 124 |
Binary Tree Maximum Path Sum |
Hard |
|
|
|
| 125 |
Valid Palindrome |
Easy |
⭐ |
string 2pointer |
沒什麼… |
| 128 |
Longest Consecutive Sequence |
Medium |
⭐ ⭐ ⭐ |
array |
題目規定要 O(n),如果不做 sort 那感覺一定大於 O(n),如果做 sort 那至少 O(nlogn),所以如果一定要 O(n),就一定是需要額外記憶體,並且可能是 O(2n) 之類的。先將其轉成 set 或 hashmap,這可以在 O(n) 完成,然後在 traverse 一次就可以有解 |
| 133 |
Clone Graph |
Medium |
⭐ ⭐ ⭐ |
graph |
沒什麼太特別的,注意不要無窮 recursion 就行了 |
| 139 |
Word Break |
Medium |
⭐ ⭐ ⭐ ⭐ |
string |
用 DP 分解這很直覺,但 iteration 應該選用走 wordDict 會比走 s 省時間。並且還有兩個優化,一是先把 wordDict decending sort;二是記住嘗試過哪個 offset 開始是無解的 |
| 141 |
Linked List Cycle |
Easy |
⭐ ⭐ ⭐ |
ll |
沒什麼,是可以用額外的 set 來記有沒有走過某的 node,不過其實這種題典型應該是用 slow fast pointer,就不需要額外空間 |
| 143 |
Reorder List |
Medium |
⭐ ⭐ ⭐ ⭐ |
ll |
O(3n) 也算 O(n),分成三步做,1 找到中點切成兩個 list,2 把後半部 reverse,3 merge 兩個 list |
| 152 |
Maximum Product Subarray |
Medium |
⭐ ⭐ ⭐ ⭐ |
array |
code 幾行就可以完成,主要是演算法要想出來。關鍵是 contiguous,對於這種有 contiguous 限制的題目特性,有一種最為常見的思考模式需要訓練一下。另外就本題來說,思考邏輯上可以是漸進式的,首先想如果都是非 0 正整數該怎麼解,然後想如果有 0 該怎麼解,最後再想如果有負數該怎麼解 |
| 153 |
Find Minimum in Rotated Sorted Array |
Medium |
⭐ ⭐ ⭐ |
search |
與 #33 Search in Rotated Sorted Array 相同且更容易 |
| 190 |
Reverse Bits |
Easy |
⭐ ⭐ ⭐ |
bit |
沒什麼 |
| 191 |
Number of 1 Bits |
Easy |
⭐ |
bit |
沒什麼 |
| 198 |
House Robber |
Medium |
⭐ ⭐ ⭐ ⭐ |
dp |
典型 DP 題,另外有關鍵是識別出可將 DP 的 recursive function call 簡化為 iteration。DP 問題只的就是每一的解會跟其他輪有關係,若後面輪次的解只跟其前面輪次有關係,那自然就可以用 iteration 即可毋需使用到 recursion |
| 200 |
Number of Islands |
Medium |
⭐ ⭐ ⭐ |
2darray |
不難想,想到後也不難做出來 |
| 206 |
Reverse Linked List |
Easy |
⭐ ⭐ ⭐ ⭐ |
ll |
基本題,recursion 和 iteration 作法都熟悉一下 |
| 207 |
Course Schedule |
Medium |
⭐ ⭐ ⭐ ⭐ |
graph dfs |
偵測單向圖中是否有循環的基本題。Recursive 走 DFS,如果走到重複的就是有循環。雖然每一個點都要為 root 去走 DFS 以避免漏掉獨立的迴圈,但可以另外透過記憶哪些點已經檢查通過了來避免重工 |
| 208 |
Implement Trie (Prefix Tree) |
Medium |
⭐ ⭐ ⭐ |
string bst |
沒什麼,就是 string 版本的 binary search tree |
| 211 |
Design Add and Search Words Data Structure |
Medium |
⭐ ⭐ ⭐ |
string |
可以用 map/dict 來實作,概念上其實變得像一棵樹 |
| 212 |
Word Search II |
Hard |
|
|
|
| 213 |
House Robber II |
Medium |
⭐ ⭐ ⭐ |
dp |
相較於 #198 House Robber 因為變成 circle 所以需要多一個關鍵想法:對於本題存在一個最佳解,那我們若任選一點 x,該點 x 只有『存在於最佳解中』和『不存在於最佳解中』兩種可能性;對於 x 不存在於最佳解中的這種可能行,本題的最佳解形同由 x+1 ~ x-1 這個 circle 的最佳解;而對於 x 存在於最佳解中的這種可能性,本題的最佳解形同由 x ~ x-2 這個 circle 的最佳解。所以若我們將 x 選為 0,那只要針對 arr[0:n-1] 和 arr[1:n] 分別去求解,再取其大者即可 |
| 217 |
Contains Duplicate |
Easy |
⭐ |
array |
暖身吧… |
| 226 |
Invert Binary Tree |
Easy |
⭐ |
tree |
暖身吧… |
| 230 |
Kth Smallest Element in a BST |
Medium |
⭐ ⭐ ⭐ |
tree bst dfs |
基本題的小延伸吧。從小排到大就是 in-order traversal,那自然可以知道第 k 小的是誰,加上一些優化就可以在得到第 k 個時就不要再繼續走下去 |
| 235 |
Lowest Common Ancestor of a Binary Search Tree |
Easy |
⭐ ⭐ ⭐ |
tree bst |
沒什麼,他是一個 BST,比 root 小的在左邊,比 root 大的在右邊,如果 p,q 都比 root 小,那 LCA 就往左邊找,反之往右邊;如果 root 值介於 p,q 之間,那 p,q 分別在 root 的左右子樹,此時找 LCA 不可能往左右字數去移動,因為一但移動,必定會失去 p,q 其中之一,這也代表 root 本身就是 LCA |
| 238 |
Product of Array Except Self |
Medium |
⭐ ⭐ ⭐ |
array |
沒做過不一定想得到,關鍵想法在 prefix 和 suffix,prefix/suffix 指的是某一個數 前面所有數/後面所有數,每一個數對應的解就是 product of prefix 乘上 product of suffix。如此一來 2 passes 就可以解出來,時間複雜度就是 O(n),並且只需要額外一塊等長的 space |
| 242 |
Valid Anagram |
Easy |
⭐ ⭐ ⭐ |
string |
#49 Group Anagrams 的基礎題 |
|
Meeting Rooms |
Medium |
|
|
|
|
Meeting Rooms II |
Medium |
|
|
|
|
Graph Valid Tree |
Medium |
|
|
|
| 268 |
Missing Number |
Easy |
⭐ ⭐ ⭐ |
array |
跟 #41 First Missing Positive 一樣,用 2n space 會很簡單,用 n space 會稍難一點 |
|
Alien Dictionary |
Medium |
|
|
|
|
Encode and Decode Strings |
Medium |
|
|
|
| 295 |
Find Median from Data Stream |
Hard |
|
|
|
| 297 |
Serialize and Deserialize Binary Tree |
Hard |
|
|
|
| 300 |
Longest Increasing Subsequence |
Medium |
⭐ ⭐ ⭐ |
array |
這種 array 類型一慣的思路都是用 greedy,就是從頭走,一步一步多看一個數字,然後去更新最佳解。但即使這題也是相同,不過沒做過還是不容易想到做法 |
| 322 |
Coin Change |
Medium |
⭐ ⭐ ⭐ ⭐ |
array |
第一個誤區是 greedy 無法解這題,例如 [23, 22, 7 ,1] 找 29,用 greedy 會得到 23+1+1+1+1+1+1,但其實 22+7 才是最佳解。但我們知道這題還是 DP,DP 就是前後輪次有關聯,比如 f(n) = g(f(n-i)),而實作就有兩種方向,若我們從 f(n) 出發,那就會變 recursion;若從 f(0) 出發,就會是 iteration |
|
Number of Connected Components in an Undirected Graph |
Medium |
|
|
|
| 338 |
Counting Bits |
Easy |
⭐ ⭐ ⭐ ⭐ |
bit |
暴力解就是 O(nlogn),如果要 O(n) 解就要有分解的 DP 想法,可已歸在 Medium 等級:一個整數 n,假設他的 binary representation 有 5 bits,那他的 1 的數量,就會是右邊 4 bits 的 1 的數量,加上最左側是否為 1,為什麼要這樣拆解?因為最左側是否為 1 這我們直接 mod 2 就可以知道,而右邊 4 bits 的 1 的數量,因該是在前面的輪次當中就已經得到答案 |
| 347 |
Top K Frequent Elements |
Medium |
⭐ ⭐ ⭐ |
array heap |
用 map 統計很容易,但統計完後要找最大的前 k 個,也就是要做 sort,且題目要 O(nlogn) 那就可以用 heap sort,沒有一定,只是本題特性上就也剛好也蠻適合就拿來練一下 heap sort |
| 371 |
Sum of Two Integers |
Medium |
⭐ ⭐ ⭐ |
bit |
Bit operation 都不適合用 python,因為 python 的 int 不受限於 32 bits,他可以很大,但為達成這個,shift bit 的行為就跟其他語言不一樣。所以這題用 C 或 Java 來做:XOR 可以得到該 bit 的結果,AND 可以得到是否要進位,recursive 直到不需進位為止 |
| 417 |
Pacific Atlantic Water Flow |
Medium |
⭐ ⭐ ⭐ |
2darray |
跟 #200 Number of Islands 有些類似。可以反著想:從 Pacific 出發可以到達的地方,以及從 Atlantic 出發可以到達的地方,這兩個部分的交集就是答案 |
| 424 |
Longest Repeating Character Replacement |
Medium |
⭐ ⭐ ⭐ ⭐ |
array |
一樣是 greedy slide window 可以解的問題,關鍵在於要認知到調整 window head 的時機是目前 window length 減去目前 window 中最常出現的那個字的次數超過 k 的時候,這代表我們就算用去 k 次機會也無法把目前的 window 都變成同一個字,所以這就是一個要縮 head 的來 recover 的時機 |
| 435 |
Non-overlapping Intervals |
Medium |
⭐ ⭐ ⭐ |
interval |
與 #56 Merge Intervals 類似 |
| 572 |
Subtree of Another Tree |
Easy |
⭐ ⭐ ⭐ ⭐ |
tree |
要實際做一下 |
| 647 |
Palindromic Substrings |
Medium |
⭐ ⭐ ⭐ |
string |
跟 #5 Longest Palindromic Substring 類似,就是細心一點做吧… |