LeetCode [26]删除有序数组中的重复项
问题描述
给你一个有序数组 nums ,请你** 原地** 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
说明:
为什么返回数值是整数,但输出的答案是数组呢?
请注意,输入数组是以**「引用」**方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。
你可以想象内部操作如下:
// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
int len = removeDuplicates(nums);
// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。
for (int i = 0; i < len; i++) {
print(nums[i]);
}
示例 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] <= 104nums已按升序排列
Related Topics
数组
双指针
答题过程
思考过程
看到这个题目,我首先看到了他说的有序数组的这个关键词,并且说在不创建新数组的前提下,完成消除重复项目,靠的是啥?靠的就是移动数组,覆盖值。
方法的开始肯定是要循环。遍历这个数组,所以,按照这个思路,就要循环比对,看当前的元素和下一个元素是否一样,如果一样就说明是重复项目,那我就需要从下一个元素开始,把数组中的元素都往前移动一个,覆盖前面的值。
按照这个思路,肯定是两层循环比对,还得有一个移动元素的操作,到这里大体的思想就是这个了。
但是有几个注意的地方。
- 数组的长度是需要动态变化的,因为这个长度涉及到比对的循环的判断,显然,不可能直接改数组的长度,那只能用一个变量,来表示数组的长度,变量的初始值就是数组的长度,在移动数组(找到重复项)的时候,数组长度减1,减1是因为一次只往前移动一位。
- 两层循环判断比较,在找到当前元素和下一个元素重复的时候,是要移动进行覆盖的,那么覆盖之后,当前元素的下一个元素要不要++呢?,这里不要++,因为下一个元素在移动的时候已经变了。换句话说,也就是,当前元素的下一个元素的移动,只有在当前元素和下一个元素不相等的时候移动,因为相等的时候要移动,这个时候下一个元素也变了,不是之前的了。
代码逻辑
public static void main(String[] args) {
// 1,1,1, 2,2,3,3,4,5
System.out.println(removeDuplicates(new int[]{1,1,12,12}));
}
public static int removeDuplicates(int[] nums) {
// 动态的长度
int length =nums.length;
// 第一层循环
for (int i = 0; i < length; i++) {
// 第二层循环
for (int i1 = i+1; i1 < length; ) {
// 两个不相等
if(nums[i] != nums[i1]){
// 只有不相等的情况下会移动。
i1++;
break;
}else{
// 相等的情况下,做元素的覆盖,一次移动只移动一个, 可以看 j-1.
for (int j = i1; j < length; j++) {
nums[j-1] = nums[j];
}
// 长度变化了,因为移动了,所以,长度变短了。
length--;
}
}
}
return length;
}