Leetcode:删除有序数组中的重复项
题目描述
给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。
由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。
将最终结果插入 nums 的前 k 个位置后返回 k 。
不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。1
判题标准
系统会用下面的代码来测试你的题解:
int[] nums = [...]; // 输入数组
int[] expectedNums = [...]; // 长度正确的期望答案
int k = removeDuplicates(nums); // 调用
assert k == expectedNums.length;
for (int i = 0; i < k; i++) {
assert nums[i] == expectedNums[i];
}
即该题目需要将removeDuplicates(nums)
方法实现
解题思路1(C++)
学过数据结构的话,很快可以想到利用 双指针 的方法来进行解题
首先根据题目要求,需要先判断nums
是否为空,若为空则k的值显然为0;当nums≥1
时,需要定义两个指针,一个快指针fast,一个慢指针slow,两个指针的初始值都指向数组下标为1的数据,因为当nums=1
时,没有需要删除的值,可以直接返回slow作为k,并且当nums>1
时,也可将slow作为k值返回,因为开始循环后,fast作为快指针永远都走在slow指针的前面,当nums[fast]==nums[fast-1]
时,fast指针向前移动一个位置,slow指针不动,当nums[fast]≠nums[fast-1]
时,将fast指针所指的数据赋值给slow指针指向的数据,并将slow指针向前移动一个位置,同时fast也要向前移动一个位置,可以结合图示来理解:
流程图(可能有误,仅供参考):
C++代码
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int size = nums.size();
int fast = 1;
int slow = 1;
if(size == 0){
return 0;
}
else{
while(fast<size){
if(nums[fast]!=nums[fast-1]){
nums[slow] = nums[fast];
slow++;
}
fast++;
}
}
return slow;
}
};
解题思路2(java)
同样的也是利用 双指针 进行解题
和上面的思路不同的是快指针和慢指针起点不同,快指针p的初始值设为1,慢指针q的初始值设置为0,当 p<nums.length
时循环开始,当 nums[p] != nums[q]
时,则将下标为p的数据赋值给下标为p+1的数据区,将下标为p+1的数据区进行覆盖,完成覆盖后,需要将慢指针q向前移动一个位置,没执行一次循环都要将快指针p向前移动一个位置,循环体结束后,返回慢指针q+1即为k的值。可以结合图示进行理解
Java代码
class Solution {
public int removeDuplicates(int[] nums) {
if(nums.length == 0)
return 0;
int p = 1;
int q = 0;
while(p<nums.length){
if(nums[p] != nums[q]){
// if(p - q>1)
nums[q+1] =nums[p];
q++;
}
p++;
}
return q+1;
}
}