本文始发于个人公众号:TechFlow,原创不易,求个关注

今天是LeetCode专题的第49篇文章,我们一起来看LeetCode的第80题,有序数组去重II(Remove Duplicates from Sorted Array II)。

这题的官方难度是Medium,通过率是43.3%,点赞1104,反对690。这题的通过率有一点点高,然后点赞比也不是很高。说明这题偏容易,并且大家的评价偏低。也的确如此,我个人觉得,大家评价不好的主要原因还是这题偏容易了一些。

题面

其实从题目的标题当中我们已经可以得到很多信息了,实际上也的确如此,这题的题面和标题八九不离十,需要我们对一个有序的数组进行去重。不过去重的条件是最多允许一个元素出现两次,也就是要将多余的元素去掉。并且题目还限制了需要我们在原数组进行操作,对于空间复杂度的要求是。由于我们去除了元素之后会带来数组长度的变化,所以我们最后需要返回完成之后数组的长度。

这是一种常规的做法,在C++以及一些古老的语言当中数组是不能变更长度的。我们想要在原数组上删除数据,只能将要删除的数据移动到数组末尾,然后返回变更之后的数组长度。这样下游就通过返回的数组长度得知变更之后的数量变化。由于新晋的一些语言,比如Java、Python都支持数组长度变动,所以很少在这些语言的代码当中看到这样的用法了。

样例

Given nums = [0,0,1,1,1,1,2,3,3],

Your function should return length = 7, with the first seven elements of nums being modified to 0, 0, 1, 1, 2, 3 and 3 respectively.

It doesn't matter what values are set beyond the returned length.

在这个样例当中,由于1出现了4次,所以我们需要删除掉2个1,那么删除之后的数组长度也会减少2,所以我们需要返回7,表示删除之后的新的数组的有效长度是7。并且保证原数组当中前5个元素是[0, 0, 1, 1, 2, 3]

题解

删除重复的元素本身并不复杂,唯一麻烦的是我们怎么在不引入额外存储的情况下完成这一点。如果你能抓住数组是有序的这一点,应该很容易想通:既然数组是有序的,那么相同的元素必然排在一起。

既然相同的元素排在一起,那么我们可以利用一个变量存储当前元素出现的次数。如果遇到不同的元素,则将次数置为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

总结

今天的题目不难,总体来说算是Medium偏低难度,主要有两点值得称道。第一点是C++风格inplace变更数组的做法,第二点就是数组自我覆盖的方法。除此之外,题目几乎没什么难度,我想大家应该都能想出解法来。

如果喜欢本文,可以的话,请点个关注,给我一点鼓励,也方便获取更多文章。

本文使用 mdnice 排版

LeetCode 80,不使用外部空间的情况下对有序数组去重的更多相关文章

  1. [leetcode]80. Remove Duplicates from Sorted Array II有序数组去重(单个元素可出现两次)

    Given a sorted array nums, remove the duplicates in-place such that duplicates appeared at most twic ...

  2. [LeetCode] Find Minimum in Rotated Sorted Array II 寻找旋转有序数组的最小值之二

    Follow up for "Find Minimum in Rotated Sorted Array":What if duplicates are allowed? Would ...

  3. [leetcode]26. Remove Duplicates from Sorted Array有序数组去重(单个元素只出现一次)

    Given a sorted array nums, remove the duplicates in-place such that each element appear only once an ...

  4. Leetcode之二分法专题-167. 两数之和 II - 输入有序数组(Two Sum II - Input array is sorted)

    Leetcode之二分法专题-167. 两数之和 II - 输入有序数组(Two Sum II - Input array is sorted) 给定一个已按照升序排列 的有序数组,找到两个数使得它们 ...

  5. [LeetCode] 153. Find Minimum in Rotated Sorted Array 寻找旋转有序数组的最小值

    Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (i.e. ...

  6. [LeetCode] 81. Search in Rotated Sorted Array II 在旋转有序数组中搜索 II

    Follow up for "Search in Rotated Sorted Array":What if duplicates are allowed? Would this ...

  7. LeetCode 108. Convert Sorted Array to Binary Search Tree (有序数组转化为二叉搜索树)

    Given an array where elements are sorted in ascending order, convert it to a height balanced BST. 题目 ...

  8. [leetcode]81. Search in Rotated Sorted Array II旋转过有序数组里找目标值II(有重)

    This is a follow up problem to Search in Rotated Sorted Array, where nums may contain duplicates. 思路 ...

  9. LeetCode 81 Search in Rotated Sorted Array II(循环有序数组中的查找问题)

    题目链接:https://leetcode.com/problems/search-in-rotated-sorted-array-ii/#/description   姊妹篇:http://www. ...

随机推荐

  1. Linux以指定用户非root用户运行程序、进程

    方式一: 使用su命令切换用户运行 su 用户名 方式二: useradd -s /sbin/nologin -M test   -s /sbin/nologin表示创建一个禁止登陆的用户(比如www ...

  2. css 图片宽度、居中、倒影

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. 浅谈SIEM

    一.概念 SIEM ( Security Information Event Management,安全信息与事件管理) Gartner的定义:安全信息和事件管理(SIEM)技术通过对来自各种事件和上 ...

  4. ASP.NET Core 依赖注入最佳实践与技巧

    ASP.NET Core 依赖注入最佳实践与技巧 原文地址:https://medium.com/volosoft/asp-net-core-dependency-injection-best-pra ...

  5. 第十届蓝桥杯JavaC组省赛真题

    试题 A: 求和 本题总分:5 分 [问题描述] 小明对数位中含有 2.0.1.9 的数字很感兴趣,在 1 到 40 中这样的数包 括 1.2.9.10 至 32.39 和 40,共 28 个,他们的 ...

  6. Java实现 LeetCode 98 验证二叉搜索树

    98. 验证二叉搜索树 给定一个二叉树,判断其是否是一个有效的二叉搜索树. 假设一个二叉搜索树具有如下特征: 节点的左子树只包含小于当前节点的数. 节点的右子树只包含大于当前节点的数. 所有左子树和右 ...

  7. java实现和为定值的两个数

    1 问题描述 输入一个整数数组和一个整数,在数组中查找两个数,满足他们的和正好是输入的那个整数.如果有多对数的和等于输入的整数,输出任意一对即可.例如,如果输入数组[1,2,4,5,7,11,15]和 ...

  8. java实现找素数

    ** 找素数** 素数就是不能再进行等分的整数.比如:7,11.而9不是素数,因为它可以平分为3等份.一般认为最小的素数是2,接着是3,5,- 请问,第100002(十万零二)个素数是多少? 请注意: ...

  9. java实现第七届蓝桥杯寒假作业

    题目6.寒假作业 寒假作业 现在小学的数学题目也不是那么好玩的. 看看这个寒假作业: □ + □ = □ □ - □ = □ □ × □ = □ □ ÷ □ = □ (如果显示不出来,可以参见[图1. ...

  10. PAT 科学计数法

    科学计数法是科学家用来表示很大或很小的数字的一种方便的方法,其满足正则表达式 [+-][1-9].[0-9]+E[+-][0-9]+,即数字的整数部分只有 1 位,小数部分至少有 1 位,该数字及其指 ...