? 📝 題目:移除元素
? 題目描述: 給定數組和值val,原地移除所有等于val的元素,返回新長度。
? 例子: nums = [3,2,2,3], val = 3 → nums = [2,2,_,_], return 2
? 🔥 暴力法思路:
? 暴力法想法:
? "我要刪除所有等于val的元素,
那我就從頭開始找,
遇到一個val就刪除它,
然后所有后面的元素都向前移動一位。"
? 暴力法代碼:
? def removeElement_brute(nums, val):i = 0while i < len(nums):if nums[i] == val:# 刪除當前元素:所有后面元素前移for j in range(i, len(nums) - 1):nums[j] = nums[j + 1]nums.pop() ?# 刪除最后一個元素# 注意:i不自增,因為刪除后要檢查新的nums[i]else:i += 1return len(nums)
? 暴力法執行過程:
? 初始: [3, 2, 2, 3], val = 3
? i=0: nums[0]=3==val,刪除
刪除后: [2, 2, 3, _],長度變成3
? i=0: nums[0]=2!=val,i++
? i=1: nums[1]=2!=val,i++
? i=2: nums[2]=3==val,刪除
刪除后: [2, 2, _, _],長度變成2
? 結束: 返回2
? 暴力法問題: 每次刪除都要移動大量元素,效率低!
● 🎯 雙指針法思路(快慢指針):
? 雙指針法想法:
? "我不刪除元素,而是重新整理數組!
用兩個指針:
- slow指針:指向下一個要放入好元素的位置
- fast指針:遍歷所有元素
如果fast指向的元素不是val,就放到slow位置"
? 核心理念: "覆蓋代替刪除"
? 不要真的刪除,而是用好的元素覆蓋壞的位置!
? 雙指針法代碼:
? def removeElement_two_pointers(nums, val):slow = 0 ?# 慢指針:下一個好元素要放的位置for fast in range(len(nums)): ?# 快指針:遍歷所有元素if nums[fast] != val: ? ? ?# 如果是好元素nums[slow] = nums[fast] ?# 放到slow位置slow += 1 ? ? ? ? ? ? ? ?# slow后移return slow ?# slow就是新數組的長度
? 雙指針法執行過程:
? 初始: [3, 2, 2, 3], val = 3
slow=0, fast=0
? fast=0: nums[0]=3==val,跳過
slow=0 不變
? fast=1: nums[1]=2!=val,是好元素
nums[0] = nums[1] = 2
數組變成: [2, 2, 2, 3]
slow = 1
? fast=2: nums[2]=2!=val,是好元素
nums[1] = nums[2] = 2
數組變成: [2, 2, 2, 3]
slow = 2
? fast=3: nums[3]=3==val,跳過
slow=2 不變
? 結果: 數組前2位是[2,2],返回長度2
? 🔍 雙指針法的巧妙之處:
? 1. 兩個指針的分工:
? slow指針:維護"已整理好的部分"
fast指針:探索"還沒處理的部分"
? 2. 狀態變化:
? 初始: [需要處理的部分 ? ? ? ? ?]
slow=0
? 進行中: [已整理好] [需要處理的部分]
↑slow ? ? ?↑fast
? 最終: [已整理好] [垃圾區域]
↑slow
● 🧠 兩種方法的思維對比:
? | 維度 ? ?| 暴力法思維 ? | 雙指針法思維 ?|
|-------|---------|---------|
| 操作方式 ?| 真實刪除元素 ?| 覆蓋重排元素 ?|
| 思考角度 ?| "刪掉壞的" ?| "保留好的" ?|
| 處理策略 ?| 遇到壞元素就刪 | 遇到好元素就搬 |
| 時間復雜度 | O(n2) ? | O(n) ? ?|
| 空間復雜度 | O(1) ? ?| O(1) ? ?|
? 💭 思維轉換的關鍵:
? 暴力法思維:
? "我要刪除所有val=3的元素"
↓ 直接但低效
真的去刪除和移動
? 雙指針法思維:
? "我要構建一個新數組,只包含不等于val的元素"
↓ 間接但高效
原地重新排列
? 🎯 雙指針法的核心洞察:
? 關鍵洞察1: 不需要真的刪除,只需要重新排列
關鍵洞察2: 好元素的相對順序不變
關鍵洞察3: 只關心前面的好元素,后面的垃圾不管
? 為什么雙指針法更快?
? 暴力法:每次刪除都要移動O(n)個元素 → 總共O(n2)
雙指針法:每個元素只被訪問一次,只做O(1)操作 → 總共O(n)
? ★ Insight ─────────────────────────────────────
雙指針法的精髓是"重新定義問題":從"刪除不要的元素"重新定義為"收集想要的元素"。這種思維轉換讓我們從刪除操作(需要移動大量元素)變成了覆蓋操作(只需要一次賦
值),從而大幅提升效率。
─────────────────────────────────────────────────
● 總結:暴力法="刪掉壞的",雙指針法="收集好的"。關鍵思維轉換:從刪除操作變成覆蓋操作,效率從O(n2)提升到O(n)!