双指针法总结之倚天屠龙
引言
假期在看這塊知識時,突然想到雙指針中的”快慢指針“就像是倚天劍,一前一后單向執行(就像倚天劍被滅絕師太和周芷若依次拿到那樣),就是為了測試鏈表環的問題(為了測試武當七子連環陣的環是否有問題);而”左右指針“就像屠龍刀,在使用時有一些前提:金毛獅王謝遜拿著時(數組有序啥的),然后用來進行二分搜索,加上遞歸解決Nsum問題,威猛無比
類比學習法而已,唯博君一笑耳!
雙指針技巧分類:
雙指針技巧分為兩類:
- 一類是“快慢指針(倚天劍)”,主要解決鏈表中的問題,比如典型的判定鏈表中是否包含環;
- 一類是“左右指針(屠龍刀)”,主要解決數組/字符串中的問題,比如二分搜索。
一、快慢指針法-倚天劍
快慢指針一般會初始化指向鏈表的頭結點head,前進時快指針fast在前,慢指針slow在后,巧妙解決一些鏈表中的問題。
判斷鏈表中是否有環
經典解法雙指針,一個跑得快,一個跑得慢。如果不含有環,跑的快的那個指針最終會遇到null,說明鏈表不含環;如果含有環,快指針最后會超慢指針1圈,和慢指針相遇,說明鏈表含有環。
已知鏈表中含有環,返回這個環的起始位置
解法:當快慢指針相遇時,讓其中任何一個指針指向頭結點,然后兩個指針以相同速度前進,再次相遇時所在的節點位置就是環開始的位置。
原因:假設第一次相遇時,假設慢指針slow走了k步,那么快指針走了2k步,得到快指針多了了一圈為k步。設相遇點與環的起點距離為m,那么環的起點與頭節點head的距離為k-m,也就是說從head前進k-m步就能到達環起點。巧合的是,如果從相遇點繼續前進k-m布,也恰好到達環起點。
尋找無環單鏈表的重點
笨方法:先指針遍歷一遍,記錄中節點個數為n,然后從頭再來走n/2步
優雅解法:快指針一次走兩步,慢指針一次走一步,當快指針到鏈表盡頭時,慢指針就處于鏈表的中間位置。
應用:尋找鏈表中點的一個重要作用就是對鏈表進行歸并排序。對兩部分鏈表分別排序,然后合并為有序數組。
尋找單鏈表的倒數第k個元素
還是快慢指針,讓快指針先走k步,然后快慢指針同時前進。快指針到鏈表盡頭時,慢指針所在位置就是倒數第k個鏈表節點
二、左右指針法-屠龍刀
基本用法:一般初始化為left=0,right=len(num)-1
二分搜索
左右指針在數組兩端初始化,左指針往右走,右指針往做走,直至找到目標值
兩數之和
數組有序時,就應該想到雙指針技巧。類似二分搜索,通過sum大小調節left和right的移動,直至找到目標對
翻轉數組
左右指針在數組兩端初始化,相向而行,同時交互對應的元素
滑動窗口算法
雙指針技巧的最高境界。快慢指針在數組/字符串上的應用。如果掌握了該算法,既可以解決一大類字符串匹配問題
三、左右指針法高級用法之-二分搜索算法(屠龍刀威力之一)
場景:給定一個數尋找左側邊界、尋找右側邊界
技巧:
? 1)不要出現else,而是把所有情況用else if寫清楚,這樣可以清晰展現所有細節;
? 2)計算mid時要防止溢出,推薦使用left + (right-left)/2,而不是(left + right)/2。
尋找一個數(基本二分搜索)
數組排序為有序,左右指針根據大小判斷左右指針依次相向而行,找到目標值
差異梳理:因為我們初始化right = num.length-1,決定了我們搜索區間是[left,right]
所以決定了while(left <= right),同時也決定了left=mid+1和right=mid-1
因此我們只需要找到一個target的索引即可,所以當nums[mid] == target時可以立即返回
尋找左側邊界的二分搜索
[1,2,2,2,3]返回下標1
差異梳理:因為我們初始化right = num.length,決定了我們搜索區間是[left,right)
所以決定了while(left < right),同時也決定了left=mid+1和right=mid
因為我們需要找到target的最左側索引即可,所以當nums[mid] == target時不要立即返回,而要收縮右側邊界以鎖定左側邊界
尋找右側邊界的二分搜索
[1,2,2,2,3]返回下標3
差異梳理:因為我們初始化right = num.length,決定了我們搜索區間是[left,right)
所以決定了while(left < right),同時也決定了left=mid+1和right=mid
因為我們需要找到target的最右側索引即可,所以當nums[mid] == target時不要立即返回,而要收縮左側邊界以鎖定右側邊界。 又因為收縮左側邊界時必須left = mid+1,所以無論是left還是right,必須減1
邏輯統一:
對于尋找左右邊界的二分搜索,常見的方式是使用左閉右開的"搜索區間"。我們還根據邏輯將"搜索區間"全部統一成兩端都閉,便于記憶,好記,只要稍改nums[mid] == target條件處的代碼和函數返回的代碼邏輯即可,推薦拿小本子記下內容,作為二分搜索模板。
四、左右指針法高級用法之-Nsum問題(屠龍刀威力之二)
2Sum的核心解法
笨方法:二重循環窮舉,時間復雜度O(N2),空間復雜度為O(1)
優雅方法:用空間換時間,通過哈希表記錄元素值到索引的映射,減少時間復雜度;
2Sum問題就是想教我們如何使用哈希表解決問題
2Sum問題不重復結果對
基本思路是排序加雙指針,但是會出現結果重復。出問題的地方在于sum == target條件的if分支,當給res加入結果后,lo和hi在改變1的同時,還應該跳過所有重復元素。
3Sum問題
笨方法:窮舉
優雅方法:使用遍歷第一個數然后調用2Sum,關鍵點在于不能讓第一個數重復,至于后面的2個數,復用的2Sum函數會保證他們不重復
時間復雜度O(N2)
4Sum問題
相同套路:窮舉第一個數組,然后使用3Sum解決剩下3個數,然后組合出和為target的四元組。
Num 問題
首先對nums數組排序,然后n == 2時是2Sum的雙指針解法,n > 2時就是窮舉第一個數字,然后遞歸調用計算(n-1)Sum,組裝答案
總結
以上是生活随笔為你收集整理的双指针法总结之倚天屠龙的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: oracle utl file putf
- 下一篇: Android开发实验-- 电话拨号器实