【LeetCode】26. 删除有序数组中的重复项【简单】

题目链接:【26. 删除有序数组中的重复项】
题目难度:简单


一、描述

给你一个有序数组 nums ,请你原地删除重复出现的元素,使每个元素只出现一次,返回删除后数组的新长度。

不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

说明

为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

你可以想象内部操作如下:

// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
int len = removeDuplicates(nums);

// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。
for (int i = 0; i < len; i++) {
     
    print(nums[i]);
}

输入

  • 一行:有序数组

提示

0 <= nums.length <= 3 * 104
-104 <= nums[i] <= 104
nums 已按升序排列


二、示例

示例 1

输入

[1,1,2]

输出

2 // nums = [1,2]

解释:

函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。

示例 2

输入

[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、思路

  • 注意到“有序数组”条件,因此重复的项都是挨着的
  • 从某一项开始往后找,找到第一个不相同的项,删除这两项中间的全部项
  • 可以直接覆盖掉重复项,不需要一遍一遍移动重复项后面的数组项

具体思路:

  • 使用两个指针 prev、now:
    • prev:指向第一个与之前项都不同的项,即prev项之前的项都是只出现一次的项,prev项与前面的每一项都不同,但不保证与后面的项不同
    • now:指向当前遍历到的项
  • 若now项不等于prev项,则prev指针指向下一项,将now项复制到 prev项,
  • now指针指向下一项

2、复杂度

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

3、实现

class Solution {
     
public:
    int removeDuplicates(vector<int> &nums) {
     
        int size = nums.size();
        if (!size)
            return 0;
        int prev = 0;
        for (int now = 1; now < size; now++) {
     
            if (nums[now] != nums[prev]) {
     
                prev++;
                nums[prev] = nums[now];
            }
        }
        return prev + 1;
    }
};

注意:

...
if (!size)
	return 0;
...
}
  • 不能漏掉数组为空的情况,需要单列出来

4、改进

参考题解:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/solution/shuang-zhi-zhen-shan-chu-zhong-fu-xiang-dai-you-hu/

考虑情况:[0, 1, 2, 3, 4]

if (nums[now] != nums[prev]) {
     
    prev++;
    nums[prev] = nums[now];
}

发现该部分代码在该情况下会导致数组项原地复制,因此可以在prev自增1后添加判断:

  • 若 now > prev,则进行复制

改进代码

class Solution {
     
public:
    int removeDuplicates(vector<int> &nums) {
     
        int size = nums.size();
        if (!size)
            return 0;
        int prev = 0;
        for (int now = 1; now < size; now++) {
     
            if (nums[now] != nums[prev]) {
     
                prev++;
                if (now > prev)
                    nums[prev] = nums[now];
            }
        }
        return prev + 1;
    }
};

你可能感兴趣的:(LeetCode,数据结构,leetcode,算法)