刷題時最怕遇到什么?不是遞歸,不是動態規劃,是那種看起來暴力就能解、但一提交就超時的大數組問題。三數之和與四數之和就是典型代表。暴力解法分別要到 O(n3) 和 O(n?),數據量稍大就扛不住。但換個思路,用排序加雙指針,復雜度直接掉到 O(n2) 和 O(n3)。這篇把核心邏輯拆清楚,看完能直接上手寫代碼。
先說三數之和。題目要求找出數組中所有和為零的不重復三元組。輸入 [-1, 0, 1, 2, -1, -4],輸出應該是 [-1, -1, 2] 和 [-1, 0, 1] 這兩組。暴力做法是三層循環枚舉所有組合,O(n3) 的復雜度,n 超過 1000 就明顯吃力。
![]()
優化從排序開始。數組排好序后,固定一個數,剩下就變成"找兩個數湊出某個目標和"的經典問題。比如固定了 -1,就需要找兩個數加起來等于 1。這時候雙指針登場:一個放在固定位置的右邊,一個放在數組末尾。和小了,左指針右移讓總和變大;和大了,右指針左移讓總和變小。找到匹配的就記錄,然后兩邊都跳過重復值繼續。
![]()
為什么排序后雙指針有效?因為有序數組里,左移指針一定減小當前和,右移指針一定增大當前和。這個單調性保證了不會漏解,也避免了無意義的遍歷。整個過程中,外層循環固定 n 個數,內層雙指針最多走 n 步,總復雜度 O(n2)。去重也簡單:固定元素時跳過重復的,找到解后兩個指針各自跳過重復值即可。
四數之和的邏輯幾乎一樣,只是多固定一層。先排序,然后外層兩個嵌套循環固定前兩個數,剩下兩個數用雙指針找。比如數組 [1, 0, -1, 0, -2, 2] 目標和為 0,固定 -2 和 -1 后,就變成找兩個數湊 3。雙指針同樣適用:左指針從第三個位置開始,右指針在末尾,根據和的大小調整位置。
復雜度對比很直觀。四數之和暴力是 O(n?),四層循環每個數都試。優化后兩層循環加雙指針,O(n3)。對于面試常見的 10? 級別數據量,這意味著從幾小時運算降到幾秒可完成。
![]()
雙指針的價值不止這兩道題。它本質是利用有序結構的單調性,把"枚舉所有可能"變成"有方向地收縮搜索空間"。兩數之和、盛最多水的容器、滑動窗口最大值,底層都是這個思想。掌握之后,看到"有序數組""找滿足條件的對/組"這類關鍵詞,本能就會往雙指針方向想。
最后提一個容易踩的坑:去重邏輯必須和指針移動配合好。三數之和里,找到一組解后,左右指針都要跳過所有相同值再移動,否則 [-1, 0, 0, 0, 1] 這種數據會輸出多個 [ -1, 0, 1]。固定元素的循環也一樣,當前數和前一個相同就直接 continue,避免重復固定。
這兩道題的代碼實現細節很多,但核心就三點:排序創造單調性、固定 k-2 個數把 k 數之和降為雙指針問題、嚴格去重保證結果唯一。把這個框架吃透,五數之和、六數之和也能舉一反三。
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.