删除有序数组中的重复项
给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。
考虑 nums 的唯一元素的数量为 k。去重后,返回唯一元素的数量 k。
nums 的前 k 个元素应包含 排序后 的唯一数字。下标 k - 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 。不需要考虑数组中超出新长度后面的元素。
提示:
1 <= nums.length <= 3 * 10e4
-100 <= nums[i] <= 100
nums 已按 非递减 顺序排列。
题解
方法:快慢指针法,用一个慢指针 i 指向“已处理区域的最后一个位置”,用一个快指针 j 遍历整个数组,当快指针遇到与慢指针指向元素不同的新元素时,就将其移到慢指针的下一个位置,然后慢指针前进一步。
第一版:
我试图用嵌套的 while 循环来跳过重复元素。这个版本虽然能通过测试,但逻辑比较绕,内层 while 负责跳过重复,外层负责移动指针。代码中还需要特别处理边界情况(j < nums.size()-1),否则容易越界,整体可读性较差。
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int i=0,j=0;
while(j<nums.size())
{
while(nums[i]==nums[j])
{
if(j<nums.size()-1) j++;
else return i+1;
}
nums[i+1]=nums[j];
i++;
}
return i;
}
};
第二版:
用 if-else 结构替代了嵌套循环,发现其实没必要多写一个while,但整体还是比较混乱。
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int i=0,j=0;
while(j<nums.size())
{
if(nums[i]!=nums[j])
{
nums[i+1]=nums[j];
i++;
}
else
{
if(j<nums.size()-1) j++;
else return i+1;
}
}
return i;
}
};
第三版:
直接用for循环,逻辑清晰很多,代码也更简洁了,无需额外处理边界情况。
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int i = 0;
for(int j=0;j<nums.size();j++)
{
if(nums[i]!=nums[j])
{
nums[i+1]=nums[j];
i++;
}
}
return i+1;
}
};
碎碎念:思路有,但逻辑表达有待提升,再回看一遍怎么能写出这么混乱的代码(指第一版

浙公网安备 33010602011771号