方法:雙指針法
算法
數組完成排序後,我們可以放置兩個指針 i和 j,其中 i 是慢指針,而 j 是快指針。只要 nums[i]=nums[j],我們就增加 j 以跳過重複項。
當我們遇到nums[j] =nums[i] 時,跳過重複項的運行已經結束,因此我們必須把它(nums[j])的值複製到 nums[i + 1]。然後遞增 i,接着我們將再次重複相同的過程,直到 j 到達數組的末尾爲止
public int removeDuplicates(int[] nums) {
if (nums.length == 0) return 0;
int i = 0;
for (int j = 1; j < nums.length; j++) {
if (nums[j] != nums[i]) {
i++;
nums[i] = nums[j];
}
}
return i + 1;
}
複雜度分析
時間複雜度: O(n),假設 n 是列表的長度,那麼 i 和 j 分別最多遍歷 n 步。
空間複雜度: O(1)
方法二:覆蓋多餘的重複項
算法:
1.我們使用了兩個指針,i 是遍歷指針,指向當前遍歷的元素;j 指向下一個要覆蓋元素的位置。
2.同樣,我們用 count 記錄當前數字出現的次數。count 的最小計數始終爲 1。
3.我們從索引 1 開始一次處理一個數組元素。
4.若當前元素與前一個元素相同,即 nums[i]==nums[i-1],則 count++。若 count > 2,則說明遇到了多餘的重複項。在這種情況下,我們只向前移動 i,而 j 不動。
5.若 count <=2,則我們將 i 所指向的元素移動到 j 位置,並同時增加 i 和 j。
6.若當前元素與前一個元素不相同,即 nums[i] != nums[i - 1],說明遇到了新元素,則我們更新 count = 1,並且將該元素移動到 j 位置,並同時增加 i 和 j。
7.當數組遍歷完成,則返回 j。
class Solution {
public int removeDuplicates(int[] nums) {
//
// Initialize the counter and the second pointer.
//
int j = 1, count = 1;
//
// Start from the second element of the array and process
// elements one by one.
//
for (int i = 1; i < nums.length; i++) {
//
// If the current element is a duplicate, increment the count.
//
if (nums[i] == nums[i - 1]) {
count++;
} else {
//
// Reset the count since we encountered a different element
// than the previous one.
//
count = 1;
}
//
// For a count <= 2, we copy the element over thus
// overwriting the element at index "j" in the array
//
if (count <= 2) {
nums[j++] = nums[i];
}
}
return j;
}
}
複雜度分析
時間複雜度:O(N),我們遍歷每個數組元素一次。
空間複雜度:O(1)。