3分钟
LeetCode算法手记:26.删除有序数组中的重复项
给你一个有序数组 nums ,请你原地删除重复出现的元素,使每个元素只出现一次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
说明:
为什么返回数值是整数,但输出的答案是数组呢?
请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。
示例 1:
输入:nums = [1,1,2]
输出:2, nums = [1,2]
解释:函数应该返回新的长度2,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。
示例 2:
输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]
解释:函数应该返回新的长度 5,并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。
提示:
0 <= nums.length <= 3*104
-104 <= nums[i] <= 104
nums已按升序排列
思路
定义快慢指针,在快指针从前向后遍历的过程中,如果遇到新的值和当前慢指针的值不同,则慢指针向后递进一格并替换慢指针当前的值为快指针的值,这样就能跳过重复的元素,最后返回慢指针指向的下标+1(从0开始)就能得到正确的答案。
思路递推
以示例二中的 nums = [0,0,1,1,1,2,2,3,3,4]进行递推:
-
定义慢指针i,快指针j,初始i = 0,j = 0。
-
此时nums[i] = 0,nums[j] = 0,二者相等,慢指针i不动,快指针j继续向后递进。
-
i = 0,j = 1。
-
此时nums[i] = 0,nums[j] = 0,二者相等,慢指针i不动,快指针j继续向后递进。
-
i = 0,j = 2。
-
此时nums[i] = 0,nums[j] = 1,二者不相等,慢指针i向后递进,并替换当前nums[i]的值为nums[j],快指针j继续向后递进。
-
i = 1,j = 3。
-
此时nums[i] = 1,nums[j] = 2,二者相等,慢指针i不动,快指针j继续向后递进。
-
i = 1,j = 4。
-
此时nums[i] = 1,nums[j] = 2,二者相等,慢指针i不动,快指针j继续向后递进。
-
i = 1,j = 5。
-
此时nums[i] = 1,nums[j] = 2,二者不相等,慢指针i向后递进,并替换当前nums[i]的值为nums[j],快指针j继续向后递进。
-
i = 2,j = 6。
-
此时nums[i] = 2,nums[j] = 2,二者相等,慢指针i不动,快指针j继续向后递进。
-
i = 2,j = 7。
-
此时nums[i] = 2,nums[j] = 3,二者不相等,慢指针i向后递进,并替换当前nums[i]的值为nums[j],快指针j继续向后递进。
-
i = 3,j = 8。
-
此时nums[i] = 3,nums[j] = 3,二者相等,慢指针i不动,快指针j继续向后递进。
-
i = 3,j = 9。
-
此时nums[i] = 3,nums[j] = 4,二者不相等,慢指针i向后递进,并替换当前nums[i]的值为nums[j],快指针j继续向后递进。
-
此时快指针到达末尾,退出循环,答案为慢指针i+1,即为5。
代码实现
public static int removeDuplicates(int[] nums) {
int length = nums.length;
//定义快慢指针,只有当快指针的值和慢指针不相等时,慢指针前进一格并替换当前快指针的值
int i = 0,j = 0;
while (j < length){
if (nums[i] != nums[j]){
i++;
nums[i] = nums[j];
}
j++;
}
return i+1;
}
public static void test(){
System.out.println(removeDuplicates(new int[]{0,0,1,1,1,2,2,3,3,4}));
}