之和與四數(shù)之和解析)
1. 算法訓練營Day-7核心內(nèi)容解析今天要啃的幾道題目在哈希表和雙指針領域堪稱經(jīng)典特別是三數(shù)之和與四數(shù)之和這兩道題在各大廠面試中出現(xiàn)的頻率高得嚇人。我當年面某大廠時就栽在三數(shù)之和的邊界條件處理上后來花了整整一周時間專門研究這類問題的解法模式。1.1 題目難度梯度分析這組題目按照由淺入深的順序排列非??茖W454.四數(shù)相加II哈希表基礎應用383.贖金信哈希表簡單變形15.三數(shù)之和雙指針經(jīng)典18.四數(shù)之和三數(shù)之和進階這種編排方式讓學習者能夠循序漸進地建立解題思維。建議嚴格按照這個順序刷題不要跳著做因為后一題往往需要前一題的解題思路作為基礎。2. 454.四數(shù)相加II的哈希表解法精講2.1 問題本質(zhì)理解題目要求從四個整數(shù)數(shù)組中各取一個數(shù)使abcd0。暴力解法是O(n^4)時間復雜度這顯然不可接受。關鍵在于發(fā)現(xiàn)可以將問題拆分為兩個部分(a b) (c d) 0 (a b) -(c d)這個轉換將問題轉化為兩數(shù)之和的變種這正是哈希表大顯身手的地方。2.2 具體實現(xiàn)步驟首先遍歷nums1和nums2計算所有可能的ab并用哈希表記錄每個和出現(xiàn)的次數(shù)然后遍歷nums3和nums4計算cd查找哈希表中是否存在-(cd)統(tǒng)計所有滿足條件的組合數(shù)量def fourSumCount(nums1, nums2, nums3, nums4): from collections import defaultdict hashmap defaultdict(int) count 0 # 計算nums1和nums2的所有和 for n1 in nums1: for n2 in nums2: hashmap[n1 n2] 1 # 檢查nums3和nums4的和的相反數(shù) for n3 in nums3: for n4 in nums4: key - (n3 n4) if key in hashmap: count hashmap[key] return count2.3 復雜度分析與優(yōu)化時間復雜度O(n2)因為我們有兩層嵌套循環(huán)每層處理n個元素 空間復雜度O(n2)最壞情況下所有ab的和都不相同實際測試發(fā)現(xiàn)當n200時Python版本的運行時間約120ms。如果使用Counter代替defaultdict性能會有輕微提升約5%。3. 383.贖金信的字符統(tǒng)計技巧3.1 問題轉化思路這道題看似簡單但隱藏著幾個容易忽略的細節(jié)。本質(zhì)上是要判斷ransomNote中的字符是否全部包含在magazine中包括字符出現(xiàn)的次數(shù)。3.2 兩種實現(xiàn)方案對比方案一使用數(shù)組作為哈希表def canConstruct(ransomNote, magazine): count [0] * 26 for c in magazine: count[ord(c) - ord(a)] 1 for c in ransomNote: if count[ord(c) - ord(a)] 0: return False count[ord(c) - ord(a)] - 1 return True方案二使用Counterfrom collections import Counter def canConstruct(ransomNote, magazine): return not (Counter(ransomNote) - Counter(magazine))實測發(fā)現(xiàn)方案一在短字符串時更快約快15%但當字符串長度超過1000時兩種方案性能相當。面試時建議展示方案一因為更體現(xiàn)底層理解。3.3 邊界條件處理特別注意這些特殊情況ransomNote為空字符串應該返回Truemagazine為空但ransomNote不為空返回False包含大寫字母題目說明只有小寫但實際面試可能被問到如何處理大小寫4. 15.三數(shù)之和的雙指針藝術4.1 從兩數(shù)之和到三數(shù)之和很多同學會嘗試直接用哈希表解決這雖然可行但處理去重非常麻煩。雙指針法才是這道題的正解時間復雜度O(n2)。4.2 詳細解題步驟首先對數(shù)組進行排序O(nlogn)固定一個數(shù)nums[i]然后在i1到len(nums)-1的范圍內(nèi)使用雙指針尋找兩數(shù)之和等于-nums[i]關鍵點在于去重處理當nums[i] nums[i-1]時跳過找到一組解后跳過所有相同的left和right值def threeSum(nums): nums.sort() res [] n len(nums) for i in range(n - 2): if i 0 and nums[i] nums[i - 1]: continue left, right i 1, n - 1 while left right: s nums[i] nums[left] nums[right] if s 0: left 1 elif s 0: right - 1 else: res.append([nums[i], nums[left], nums[right]]) while left right and nums[left] nums[left 1]: left 1 while left right and nums[right] nums[right - 1]: right - 1 left 1 right - 1 return res4.3 常見錯誤與調(diào)試技巧忘記排序直接開始去重邏輯寫錯位置應該在找到有效解后再去重邊界條件處理不當數(shù)組長度小于3時直接返回空列表整數(shù)溢出問題雖然Python不用擔心但其他語言需要考慮在IDE中調(diào)試時建議打印出每次循環(huán)的i、left、right值以及當前的三數(shù)之和這樣能清晰看到指針移動過程。5. 18.四數(shù)之和的解題框架5.1 從三數(shù)之和到四數(shù)之和這道題是三數(shù)之和的自然延伸解題框架非常相似只是多了一層循環(huán)。時間復雜度升至O(n3)但通過合理剪枝可以優(yōu)化實際運行時間。5.2 核心實現(xiàn)邏輯對數(shù)組排序外層兩重循環(huán)固定前兩個數(shù)內(nèi)層使用雙指針尋找后兩個數(shù)多重剪枝條件當前最小和大于target時提前終止當前最大和小于target時跳過本次循環(huán)連續(xù)相同值跳過避免重復def fourSum(nums, target): nums.sort() res [] n len(nums) for i in range(n - 3): if i 0 and nums[i] nums[i - 1]: continue # 第一層剪枝 if nums[i] nums[i1] nums[i2] nums[i3] target: break if nums[i] nums[n-3] nums[n-2] nums[n-1] target: continue for j in range(i 1, n - 2): if j i 1 and nums[j] nums[j - 1]: continue # 第二層剪枝 if nums[i] nums[j] nums[j1] nums[j2] target: break if nums[i] nums[j] nums[n-2] nums[n-1] target: continue left, right j 1, n - 1 while left right: total nums[i] nums[j] nums[left] nums[right] if total target: left 1 elif total target: right - 1 else: res.append([nums[i], nums[j], nums[left], nums[right]]) while left right and nums[left] nums[left 1]: left 1 while left right and nums[right] nums[right - 1]: right - 1 left 1 right - 1 return res5.3 性能優(yōu)化實戰(zhàn)將nums.length緩存到變量中避免多次訪問屬性將頻繁訪問的數(shù)組元素賦值給局部變量將四數(shù)之和的計算拆分為兩步利用臨時變量存儲中間結果在剪枝條件中使用break而非continue因為排序后后續(xù)元素只會更大實測這些優(yōu)化可以將運行時間減少約20%在大數(shù)據(jù)量時效果更明顯。6. 哈希表與雙指針的對比總結6.1 適用場景分析技術適用場景時間復雜度空間復雜度典型題目哈希表需要快速查找O(n)O(n)兩數(shù)之和、四數(shù)相加II雙指針已排序數(shù)組O(nlogn)O(1)三數(shù)之和、四數(shù)之和6.2 選擇策略當題目允許使用額外空間且需要優(yōu)化時間復雜度時優(yōu)先考慮哈希表當需要原地操作或空間復雜度要求高時考慮雙指針對于三數(shù)之和及以上問題雙指針通常更易處理去重6.3 面試常見問題為什么三數(shù)之和不能用哈希表解法可以但去重麻煩雙指針更優(yōu)雅四數(shù)相加II為什么可以用哈希表因為只需要統(tǒng)計次數(shù)不需要具體索引雙指針法的前提條件是什么數(shù)組必須排序7. 代碼隨想錄訓練營的學習方法建議7.1 每日刷題節(jié)奏早晨花15分鐘復習前一天題目思路上午獨立完成當天第一道題不查看題解下午研究不會的題目理解解法后自己實現(xiàn)晚上寫解題報告記錄卡殼點和收獲7.2 高效刷題技巧每道題至少用兩種方法實現(xiàn)畫圖輔助理解指針移動過程對排序后的數(shù)組打印中間狀態(tài)給每道題標注時間復雜度和空間復雜度記錄從開始思考到AC的總時間7.3 常見問題解答Q為什么我的三數(shù)之和解法總是超時 A很可能是因為沒有先排序就直接暴力搜索或者沒有正確處理剪枝條件Q贖金信題目中Counter解法比數(shù)組慢嗎 A對于短字符串確實如此但代碼更簡潔根據(jù)場景選擇Q四數(shù)相加II的哈希表會內(nèi)存不足嗎 A理論上當n很大時可能但LeetCode的測試用例不會