LeetCode面试150——26删除有序数组中的重复项

题目难度:简单

默认优化目标:最小化平均时间复杂度。

Python默认为Python3。

1 题目描述

给你一个 非严格递增排列 的数组 nums ,请你原地删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。

考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:

  • 更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。

  • 返回 k

判题标准:

系统会用下面的代码来测试你的题解:

int[] nums = [...]; // 输入数组
int[] expectedNums = [...]; // 长度正确的期望答案
​
int k = removeDuplicates(nums); // 调用
​
assert k == expectedNums.length;
for (int i = 0; i < k; i++) {
    assert nums[i] == expectedNums[i];
}

如果所有断言都通过,那么您的题解将被 通过

示例 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 * 104

  • -104 <= nums[i] <= 104

  • nums 已按 非严格递增 排列

2 题目解析

输入是一个 非严格递增排列 的数组 nums,输出是nums 中唯一元素的个数k以及这些元素相对顺序不变的组成的数组nums

27移除元素不同,27中是给你要删除的值val,而本题是要删除数组中重复的元素。就像所给示例中展示的。

题目描述中有这么一句话,"nums 的其余元素与 nums 的大小不重要",这就意味着我们只要保证nums 的前 k 个元素包含唯一元素,而不需要真的从数组中将这些重复元素删除。

同时,由于输入的是非严格递增排列 的数组,相对顺序不变的意思就是升序排序。由于已经保证了非严格递增排列,因此排序操作也是不需要的。

综上,这道题只涉及交换操作。双指针应该是第一时间能想到的方法。

3 算法原理及程序实现

3.1 双指针

由于输出的要求是保证nums 的前 k 个元素包含唯一元素,所以两个指针都指向头节点。一个由于遍历数组,一个用于定位非重复元素的位置。如果元素不重复,就用当前元素去替换非重复元素后面的那一个元素值。

记定位非重复元素的位置的指针为left,遍历数组的指针为rightright从数组下标位置1开始到n-1结束,left0开始到n-2结束,nnums的长度。right是连续的,即在大循环当中+1,因为是遍历数组。left则是跳跃的,只有找到非重复元素才改变指向。要注意的是,left指向的是非重复元素的后一个位置,因此left最多取n-2。如果到n-1,会数组越界。

用这种方法要考虑两个特例,一个是空数组输入,另一个是数组长度为1。空数组直接返回0。长度为一的数组,元素必不重复,不用对数组进行操作,直接返回1即可。考虑到这种情况在测试用例中的占比必然是少数,因此判断条件先判断n>=2的情况,再是n==1,最后!n,即n==0,以提高平均运行速度。

平均实践复杂度为O(n),平均空间复杂度为O(1)。

C++代码实现

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        int left=0;
        int n=nums.size();
        int k=1;//初始长度为1
​
        if(n>=2){
            for(int right=1;right<n;right++){
                if(nums[left]!=nums[right]){
                    nums[++left]=nums[right];//left先后移一位再改变指向nums元素的值
                    k++;
                }
            }
            
        }else if(n==1){
            return k;
        }
        else{
            return 0;
        }
​
        return k;
    }
};

Python代码实现

class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        left,right=0,1
        k=1
        n=len(nums)
​
        if n>=2:
            while right<n:
                if nums[left]!=nums[right]:
                    left+=1
                    nums[left]=nums[right]
                    k+=1
                right+=1
        elif n==1:
            return k
        else:
            return 0
            
        return k
​
                

有关++left和left++的区别可以看每日一个小知识——P++和++P的区别

参考资料

力扣面试经典150题

力扣官方题解

  • 19
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值