删除有序数组中的重复项

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

给你一个 非严格递增排列 的数组 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;
    }
};

碎碎念:思路有,但逻辑表达有待提升,再回看一遍怎么能写出这么混乱的代码(指第一版

posted @ 2026-03-20 20:31  解西亚  阅读(1)  评论(0)    收藏  举报