全栈开发知识库

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

题目

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

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

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

示例 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 。不需要考虑数组中超出新长度后面的元素。

思路

双指针
- 既然非严格递增队列,那么重复的元素一定会相邻,那我们可以从0开始遍历,将没有重复的数值替换放到数组的开头

class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        # 第一个位置的不用判断
        k = 1
        for i in range(len(nums)):
            # 当前的数值与已放置的数值不同就重新放置
            if nums[i] != nums[k - 1]:
                nums[k] = nums[i]
                k += 1
        return k
class Solution {
    fun removeDuplicates(nums: IntArray): Int {
        var k = 1
        for(i in nums){
            if (i != nums[k - 1]) {
                nums[k] = i
                k ++
            }
        }
        return k
    }
}

优化:

假如数组是[0, 1, 2, 3, 4, 5] 此时数组中没有重复元素,按照上面的方法,每次比较时nums[i]都不等于nums[k - 1],因此就会将k指向的元素原地复制一遍,这个操作其实是不必要的。

优化的核心思想是:只有当当前索引 i 和写入位置 k 不相等时,才进行复制操作。

所以优化就是:只有当 i > k 时才写入

def removeDuplicates(self, nums: List[int]) -> int:
    k = 1
    for i in range(len(nums)):
        if nums[i] != nums[k - 1]:
            if i > k:
                nums[k] = nums[i]
            k += 1
    return k

一定要注意: 这里比较的是 nums[i] != nums[k -1], 而不能是i - 1。

因为i中的元素会被后面的覆盖掉,会变。 比较i - 1是不对的,而k - 1才是去重后的真实结果。


  • 邮箱 :charon.chui@gmail.com
  • Good Luck!