給定已排序數組,要求原地移除重複元素,返回新長度。LeetCode 26/80 題核心模式,雙指針法是標準解法。
public static int removeDuplicates(int[] nums) {
if (nums.length < 2) return nums.length;
int slow = 1; // 指向下一個不重複元素應放置的位置
for (int fast = 1; fast < nums.length; fast++) {
// 發現新值:nums[fast] != 已確定區域最後一個值 nums[slow-1]
if (nums[fast] != nums[slow - 1]) {
nums[slow++] = nums[fast]; // 放入並推進 slow
}
}
return slow; // 新長度
}
初始: [1, 1, 2, 2, 3]
↑ ↑
s=1 f=1
f=1: nums[1]=1 == nums[0] → 跳過
f=2: nums[2]=2 != nums[0] → nums[1]=2, s=2
[1, 2, 2, 2, 3]
f=3: nums[3]=2 == nums[1] → 跳過
f=4: nums[4]=3 != nums[1] → nums[2]=3, s=3
[1, 2, 3, 2, 3] → 返回 3,前 3 位為去重結果
public static int removeDuplicatesK(int[] nums, int k) {
if (nums.length <= k) return nums.length;
int index = k; // 前 k 個直接保留
for (int i = k; i < nums.length; i++) {
// 比較當前值與「已確定區域倒數第 k 個」
if (nums[i] != nums[index - k]) {
nums[index++] = nums[i];
}
}
return index;
}
輸入: [1,1,1,2,2,3] index=2 i=2: nums[2]=1 == nums[0] → 跳過 i=3: nums[3]=2 != nums[0] → nums[2]=2, index=3 i=4: nums[4]=2 != nums[1] → nums[3]=2, index=4 i=5: nums[5]=3 != nums[2] → nums[4]=3, index=5 結果: [1,1,2,2,3,...] 長度 5
nums[0..slow-1] / nums[0..index-1] 始終維護「已處理的合法結果區」fast / i 為掃描指針,遍歷原始數據| 指標 | 複雜度 | 說明 |
|---|---|---|
| 時間 | O(n) | 單次遍歷 |
| 空間 | O(1) | 僅使用常數額外變量 |
| 穩定性 | 穩定 | 相對順序保持 |
prev.next = curr.next 刪除節點new String(arr, 0, len)index - k 幾何含義slow 初始為 1 而非 0System.arraycopy 批量移動優化大數據場景雙指針是陣列/鏈表原地修改問題的萬能鑰,熟練掌握此模式可秒殺大量 LeetCode Easy/Medium 題。