​LeetCode刷题实战80:删除排序数组中的重复项 II

程序IT圈

共 2995字,需浏览 6分钟

 ·

2020-10-31 01:11

算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !

今天和大家聊的问题叫做 删除排序数组中的重复项 II,我们先来看题面:

https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array-ii/

Given a sorted array nums, remove the duplicates in-place such that duplicates appeared at most twice and return the new length.


Do not allocate extra space for another array; you must do this by modifying the input array in-place with O(1) extra memory.

题意


给定一个增序排列数组 nums ,你需要在 原地 删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度。

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


样例

示例 1:

输入:nums = [1,1,1,2,2,3]
输出:5, nums = [1,1,2,2,3]
解释:函数应返回新长度 length = 5, 并且原数组的前五个元素被修改为 1, 1, 2, 2, 3 。你不需要考虑数组中超出新长度后面的元素。

示例 2:

输入:nums = [0,0,1,1,1,1,2,3,3]
输出:7, nums = [0,0,1,1,2,3,3]
解释:函数应返回新长度 length = 7, 并且原数组的前五个元素被修改为 0, 0, 1, 1, 2, 3, 3 。你不需要考虑数组中超出新长度后面的元素。


解题

https://www.cnblogs.com/techflow/p/13186342.html

题解

删除重复的元素本身并不复杂,唯一麻烦的是我们怎么在不引入额外存储的情况下完成这一点。如果你能抓住数组是有序的这一点,应该很容易想通:既然数组是有序的,那么相同的元素必然排在一起。
既然相同的元素排在一起,那么我们可以利用一个变量存储当前元素出现的次数。如果遇到不同的元素,则将次数置为1。这样我们就可以判断出究竟哪些元素需要删除,哪些元素需要保留了。
但是这就又引入了另外一个问题,我们怎么来删除这些重复的元素呢?因为我们不能引入额外的数组,需要在当前数组上完成。我们可以先假设没有这个限制,我们会怎么做?

new_nums = []
cur = None
for i in range(n):
    if cur == nums[i]:
        count += 1
 else:
        count = 1
        cur = nums[i]
    if count > 2:
        continue
    new_nums.append(nums[i])


由于有这个限制,所以我们要做的就是把new_nums这个数组去掉,其实去掉是很简单的,因为我们可以让nums这个数组自己覆盖自己。因为产出的数据的数量一定是小于等于数组长度的,所以不会出现数组越界的问题。我们只需要维护一个下标记录nums数组当中允许覆盖的位置即可。
这个也是非常常见的做法,我们在之前的题目当中也曾经见到过。

class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        # start是起始覆盖指针,指向第一个可以覆盖的位置
        start, cur, cnt = 0, None, 0
        n = len(nums)
        if n == 0:
            return 0
        for i in range(n):
            if cur == nums[i]:
                cnt += 1
            else:
                cnt = 1
                cur = nums[i]
            # 如果数量超过2,说明当前元素应该舍弃,则continue
            if cnt > 2:
                continue
            # 否则用当前元素覆盖start位置,并且start移动一位
            else:
                nums[start] = nums[i]
                start += 1
        return start


关于这段代码,还有一个简化版本,我们可以把cnt变量也省略掉。因为元素是有序的,我们可以直接用nums[i]和nums[i-2]进行判断,如果相等,那么说明重复的元素一定超过了两个,当前元素需要跳过。
简化之后的代码如下:

class Solution(object):
    def removeDuplicates(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """

        i = 0
        for n in nums:
            if i < 2 or n != nums[i - 2]:
                nums[i] = n
                i += 1
        return i


好了,今天的文章就到这里,如果觉得有所收获,请顺手点个在看或者转发吧,你们的支持是我最大的动力。


上期推文:

LeetCode40-60题汇总,速度收藏!
LeetCode刷题实战61:旋转链表
LeetCode刷题实战62:不同路径
LeetCode刷题实战63:不同路径 II
LeetCode刷题实战64:最小路径和
LeetCode刷题实战66:加一
LeetCode刷题实战67:二进制求和
LeetCode刷题实战68:文本左右对齐
LeetCode刷题实战69:x 的平方根
LeetCode刷题实战70:爬楼梯
LeetCode刷题实战71:简化路径
LeetCode刷题实战72:编辑距离
LeetCode刷题实战73:矩阵置零
LeetCode刷题实战74:搜索二维矩阵
LeetCode刷题实战75:颜色分类
LeetCode刷题实战76:最小覆盖子串
LeetCode刷题实战77:组合
LeetCode刷题实战78:子集
LeetCode刷题实战79:单词搜索

浏览 22
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报