LeetCode - 删除有序数组中的重复项

一. 题目链接

LeetCode - 26. 删除有序数组中的重复项I

二. 解题思路

  1. 检查特殊情况:如果数组长度为0,即数组为空,则直接返回0,因为没有元素要处理。

  2. 初始化两个指针

    • dest 指针用来记录新数组中最后一个不重复元素的位置。由于数组至少有一个元素,dest 初始指向第一个元素的位置,即索引0。
    • cur 指针用来遍历数组,从数组的第二个元素开始,即索引1。
  3. 遍历和去重

    • 遍历整个数组,检查 cur 指向的当前元素。
    • 如果当前元素(nums[cur])与 dest 指向的元素(nums[dest])不相同,这意味着发现了一个新的不重复元素。
    • 将这个新的不重复元素复制到 dest + 1 的位置,这是因为我们要在新数组的末尾添加这个元素,并且移动 destcur 指针。
    • 如果 nums[cur]nums[dest] 相同,则仅将 cur 指针向前移动,跳过这个重复的元素。
  4. 返回新数组的长度

    • 在完成遍历之后,dest 指针的位置加1(因为索引是从0开始的)即为新数组的长度。 

三. 动画解析

四. 代码解析 

// 函数定义:移除有序数组中的重复元素,并返回新的数组长度
int removeDuplicates(int* nums, int numsSize)
{
    // 如果数组为空,则直接返回长度为0
    if(numsSize == 0)
    {
        return 0;
    }
    
    // dest指针用于记录最后一个不重复元素的位置
    int dest = 0;
    // cur指针用于遍历数组中的每一个元素
    int cur = 1;
    // 初始化,将第一个元素视为不重复元素
    nums[dest] = nums[0];
    
    // 遍历数组中除了第一个元素之外的所有元素
    while(cur < numsSize)
    {
        // 当前元素与dest位置的元素不相同,说明发现了新的不重复元素
        if(nums[cur] != nums[dest])
        {
            // 将这个新的不重复元素移动到dest+1的位置
            nums[++dest] = nums[cur++];
        }
        else
        {
            // 如果当前元素与dest位置的元素相同,跳过这个重复元素
            cur++;
        }
    }
    
    // 返回新的数组长度,因为dest是从0开始的索引,所以要加1
    return dest+1;    
}

五. 题目链接 

LeetCode - 80.删除有序数组中的重复项II

六. 解题思路

  1. 初始化变量

    • Numsize 存储数组的大小。
    • cur 是一个指针变量,开始时指向数组的第二个元素,因为我们将比较当前元素与之前的元素。
    • dest 是一个指针变量,表示新数组无重复元素的最后一个元素的索引,开始时指向第一个元素,假设它是唯一的。
    • flag 用来记录与当前元素值相同的元素出现的次数,因为每个元素最多允许出现两次,所以当遇到第一个元素时初始化为1。
  2. 特殊情况处理:如果数组的大小不超过2,那么所有元素自然都满足条件(因为每个元素最多允许出现两次),直接返回数组的大小。

  3. 遍历数组:使用 cur 指针从索引1开始遍历数组,与 dest 指针所指的元素进行比较。

  4. 复制或跳过元素

    • 如果 cur 指向的元素与 dest 指向的元素相同,且 flag 小于2,则将 cur 指向的元素复制到 dest+1 的位置,并递增 destcur,同时 flag 也递增,因为我们遇到了一个重复的元素。
    • 如果 cur 指向的元素与 dest 指向的元素相同,但 flag 大于等于2,这意味着当前元素已经至少重复了两次,所以不将它复制到新数组中,只递增 cur
    • 如果 cur 指向的元素与 dest 指向的元素不同,说明遇到了新的元素,将 cur 指向的元素复制到 dest+1 的位置,并递增 destcur,同时将 flag 重置为1。
  5. 返回新的数组长度:遍历结束后,dest+1 就是新的数组长度,因为 dest 指向新数组中最后一个元素的索引。

七. 动画解析

暂无

八. 代码解析 

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        int Numsize = nums.size();
        int cur = 1;
        int dest = 0;//默认第一个是独一无二的
        int flag = 1;//第二个元素至多可以重复一次,所以初始化flag为1,表示第一个元素已经出现过一次
        if (nums.size() <= 2)
        {
            return nums.size(); // 如果数组大小不超过2,则不需要任何操作
        }
        while (cur < Numsize)
        {
            if (nums[cur] == nums[dest] && flag < 2)
            {
                // 如果当前元素与前一个相同,但还没有重复超过一次,那么也添加到数组中
                nums[++dest] = nums[cur];
                cur++;
                flag++;
            }
            else if (nums[cur] == nums[dest] && flag >= 2)
            {
                //这种情况就不符合题目条件了
                cur++;
            }
            else
            {
                // 如果当前元素(cur)与前一个(dest)不同,那么它可以被添加到dest+1的位置中
                nums[++dest] = nums[cur];
                cur++;
                flag = 1;
            }
        }
        return dest + 1;// 数组的新长度是最后一个元素的索引 + 1
    }
};

注意

这些步骤可能忘记

if (nums.size() <= 2)
{
    return nums.size(); // 如果数组大小不超过2,则不需要任何操作
}

虽然不写不会影响代码的正确性,且对于较大的数组,这个检查对于整体性能的影响是微不足道的。但是对于小数组来说,代码将继续进行不必要的迭代,影响了性能。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值