原题
给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
示例 1:
给定 nums = [1,1,1,2,2,3], 函数应返回新长度 length =5
, 并且原数组的前五个元素被修改为1, 1, 2, 2,
3 。 你不需要考虑数组中超出新长度后面的元素。
示例 2:
给定 nums = [0,0,1,1,1,1,2,3,3], 函数应返回新长度 length =7
, 并且原数组的前五个元素被修改为0
, 0, 1, 1, 2, 3, 3 。 你不需要考虑数组中超出新长度后面的元素。
说明:
为什么返回数值是整数,但输出的答案是数组呢?
请注意,输入数组是以“引用”方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。
你可以想象内部操作如下:
// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝 int len = removeDuplicates(nums); // 在函数里修改输入数组对于调用者是可见的。 // 根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。 for (int i = 0; i < len; i++) { print(nums[i]); }
解法
思想
和leetcode26-删除排序数组中的重复项类似,这里也使用双指针,但是添加一个变量用于计数。
代码
解法一:使用额外变量count,慢指针始终停在每一组重复元素中的最多第二个元素上。
class Solution {
public int removeDuplicates(int[] nums) {
int i = 0;
int j = 0;
int count = 1;
while(j<nums.length-1){
j++;
// 如果遇到了新的字符,计数清零
if(nums[j]!=nums[j-1]) count = 0;
// 如果计数小于二,将后面那个指针指向的值赋给前面那个指针指向的值
if(count<2){
count++;
nums[++i] = nums[j];
}
}
return i+1;
}
}
解法二:慢指针停留在要检查的元素上(可能要改成别的值)
func removeDuplicates(nums []int) int {
i := 2
j := 2
if len(nums) < 2{
return len(nums)
}
for j < len(nums) {
if nums[i - 2] != nums[j]{
nums[i] = nums[j]
i ++
}
j ++
}
return i
}
用遍历代替快指针的另一种写法:
func removeDuplicates(nums []int) int {
return process(nums, 2)
}
func process(nums []int, k int) int {
slow := 0
for _, v := range nums {
if slow < k || nums[slow-k] != v {
nums[slow] = v
slow++
}
}
return slow
}
原创文章,作者:彭晨涛,如若转载,请注明出处:https://www.codetool.top/article/leetcode80-%e5%88%a0%e9%99%a4%e6%8e%92%e5%ba%8f%e6%95%b0%e7%bb%84%e4%b8%ad%e7%9a%84%e9%87%8d%e5%a4%8d%e9%a1%b9ii/