演算法Tips大總結

Tech In Pieces發表於2021-01-03

Two Pointers:

針對雙指標滑動視窗的經典寫法: 右指標不斷往右邊移,移動到不能往右邊繼續移動為止(究竟什麼是不能動了 就根據具體的題目來定)當右指標到最右邊以後 開始挪動左指標 釋放視窗左邊界。(經典題目:第 3 題,第 76 題,第 209 題,第 424 題,第 438 題,第 567 題,第 713 題,第 763 題,第 845 題,第 881 題,第 904 題,第 978 題,第 992 題,第 1004 題,第 1040 題,第 1052 題。特別經典的題目:第 239 題,第 480 題。)
快慢雙指標可以查詢重複。
雙向雙指標或者多指標可以解決N sum問題。

LinkedList:

注意dummy node的使用。只要是頭部節點有可能出現變動 我們是一定需要dummy node的。
大體上 連結串列的題型,無非是:區間逆序,找中間節點或者正數或者是倒數第K隔節點。K路歸併節點,連結串列排序(這裡說的排序是指把一個連結串列的內部節點進行排序,而解決的方法只有一種方式:歸併排序),判斷是否有環以及環的起點在哪裡。

Stack:

常見的問題:
括號匹配問題以及類似問題。
棧的基本pop和push操作
利用棧進行編碼的問題 LC394 LC682 LC856 LC880
需要利用單調棧來解的問題(就是說利用棧維護一個單調遞增或者遞減的下標陣列)

Backtracking

排列問題
組合問題
排列組合雜交問題:LC1079
數獨問題
四個方向搜尋(flood fill)
subset
trie
BFS優化(因為BFS本質上是complete search 而backtracking實際上是剪枝的,也就是優化版本的BFS/DFS)

Binary Search

參見本博主的:模板題目:Binary Search (35. Search Insert Position)
注意其他的可以用二分搜尋的題目:比如那些基本有序的陣列:在山峰陣列中找山峰,在旋轉有序陣列中找分界點。第 33 題,第 81 題,第 153 題,第 154 題,第 162 題,第 852 題。
max-min 最大值最小化問題。求在最小滿足條件的情況下的最大值。第 410 題,第 875 題,第 1011 題,第 1283 題。

Sort

如果想深刻理解多路快排 請參見LC75
想理解桶排序和基數排序 LC164
擺動排序:LC324

Union Find

靈活使用並查集的思想,**熟練掌握並查集的模板,模板中有兩種並查集的實現方式,一種是路徑壓縮 + 秩優化的版本,另外一種是計算每個集合中元素的個數 + 最大集合元素個數的版本,**這兩種版本都有各自使用的地方。能使用第一類並查集模板的題目有:第 128 題,第 130 題,第 547 題,第 684 題,第 721 題,第 765 題,第 778 題,第 839 題,第 924 題,第 928 題,第 947 題,第 952 題,第 959 題,第 990 題。能使用第二類並查集模板的題目有:第 803 題,第 952 題。第 803 題秩優化和統計集合個數這些地方會卡時間,如果不優化,會 TLE。
並查集是一種思想,有些題需要靈活使用這種思想,而不是死套模板,如第 399 題,這一題是 stringUnionFind,利用並查集思想實現的。這裡每個節點是基於字串和 map 的,而不是單純的用 int 節點編號實現的。
**有些題死套模板反而做不出來,**比如第 685 題,這一題不能路徑壓縮和秩優化,因為題目中涉及到有向圖,需要知道節點的前驅節點,如果路徑壓縮了,這一題就沒法做了。這一題不需要路徑壓縮和秩優化。
靈活的抽象題目給的資訊,將給定的資訊合理的編號,使用並查集解題,並用 map 降低時間複雜度,如第 721 題,第 959 題。
關於地圖,磚塊,網格的題目,可以新建一個特殊節點,將四周邊緣的磚塊或者網格都 union() 到這個特殊節點上。第 130 題,第 803 題。
能用並查集的題目,一般也可以用 DFS 和 BFS 解答,只不過時間複雜度會高一點。

Segment Tree

線段樹的經典陣列實現寫法。將合併兩個節點 pushUp 邏輯抽象出來了,可以實現任意操作(常見的操作有:加法,取 max,min 等等)。第 218 題,第 303 題,第 307 題,第 699 題。
計數線段樹的經典寫法。第 315 題,第 327 題,第 493 題。
線段樹的樹的實現寫法。第 715 題,第 732 題。
區間懶惰更新。第 218 題,第 699 題。
離散化。離散化需要注意一個特殊情況:假如三個區間為 [1,10] [1,4] [6,10],離散化後 x[1]=1,x[2]=4,x[3]=6,x[4]=10。第一個區間為 [1,4],第二個區間為 [1,2],第三個區間為 [3,4],這樣一來,區間一 = 區間二 + 區間三,這和離散前的模型不符,離散前,很明顯,區間一 > 區間二 + 區間三。正確的做法是:在相差大於 1 的數間加一個數,例如在上面 1 4 6 10 中間加 5,即可 x[1]=1,x[2]=4,x[3]=5,x[4]=6,x[5]=10。這樣處理之後,區間一是 1-5 ,區間二是 1-2 ,區間三是 4-5 。
靈活構建線段樹。線段樹節點可以儲存多條資訊,合併兩個節點的 pushUp 操作也可以是多樣的。第 850 題,第 1157 題。

相關文章