题目:
给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
示例:
输入: nums = [1,1,1,2,2,3]
输出: 5, nums = [1,1,2,2,3]
解释: 函数应返回新长度 length = 5, 并且原数组的前五个元素被修改为 1, 1, 2, 2, 3。 不需要考虑数组中超出新长度后面的元素。
解析:
使用快慢指针,每次循环都用快指针去判断当前元素是否超过2个,如果超过,则将数组前移,for循环结束标志为快指针=数组长度-每次前移的位数。
代码实现:
public static int removeDuplicates(int[] nums) {
// 使用n记录fast指针的数出现的次数, offset代表每次少走的路,如果数组前移了offset,则offset之后不用再遍历
int slow,fast,n=1,offset=0;
// 循环结束标志为fast指针走到数组中所有数字最多出现两次的数组长度
for (fast = 1, slow = 1; fast < nums.length-offset; fast++) {
if(nums[fast]==nums[fast-1]){
n++;
if(n==2){
slow++;
}
}else{
// 如果当前位置的数与前一位不同时,且出现次数>2时,则当前位置及后面的数需要向前移n位置
if(n>2){
for (int i = fast,j=slow; i < nums.length; i++,j++) {
nums[j]=nums[i];
}
// n-2代表如果当前数有大于两个时,则偏移时需要保留2个
offset = offset + (n - 2);
fast = slow;
}
// n用完归位
n=1;
slow++;
}
}
return slow;
}
这种实现方式比较耗时,另外学习一下力扣大佬的实现思路,也是用的快慢指针,每次循环,判断快指针与慢指针-2所指的数是否相同,如果不相同,则代表,fast位置的数需要前移,代码如下:我只想说大佬牛比!
public static int removeDuplicates3(int[] nums) {
int len = nums.length;
if(len <= 2){
return len;
}
int slow = 2; int fast = 2;
while(fast < len){
if(nums[slow - 2] != nums[fast]){
nums[slow] = nums[fast];
slow++;
}
fast++;
}
return slow;
}