方法:双指针法
算法
数组完成排序后,我们可以放置两个指针 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)。