本文始发于个人公众号: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. 《学习scrapy框架爬小说》的进一步完善

    一.完善目标: 1.为方便使用,把小说拼音或英文名,小说输出中文名,第一章节url地址变量化,修改这些参数即可爬取不同的小说. 2.修改settings.py设置文件,配置为记录debug的log信息 ...

  2. Alpha冲刺 —— 5.8

    这个作业属于哪个课程 软件工程 这个作业要求在哪里 团队作业第五次--Alpha冲刺 这个作业的目标 Alpha冲刺 作业正文 正文 github链接 项目地址 其他参考文献 无 一.会议内容 1.展 ...

  3. Chisel3-Intellij IDEA中使用sbt构建Chisel项目

    https://mp.weixin.qq.com/s/gssjiiPW6zUzKwCFZdNduw   1. 使用Intellij IDEA创建Scala项目   Chisel项目,就是构建Scala ...

  4. Java实现 LeetCode 668 乘法表中第k小的数(二分)

    668. 乘法表中第k小的数 几乎每一个人都用 乘法表.但是你能在乘法表中快速找到第k小的数字吗? 给定高度m .宽度n 的一张 m * n的乘法表,以及正整数k,你需要返回表中第k 小的数字. 例 ...

  5. Java实现 LeetCode 474 一和零

    474. 一和零 在计算机界中,我们总是追求用有限的资源获取最大的收益. 现在,假设你分别支配着 m 个 0 和 n 个 1.另外,还有一个仅包含 0 和 1 字符串的数组. 你的任务是使用给定的 m ...

  6. Java实现 谁不爱打牌

    谁不爱打牌 [问题描述] BobLee最近在复习考研,但是他也喜欢打牌(有谁不爱玩牌呢?).但是作为一名ACMER,斗地主显然满足不了他的兴趣, 于是他和YYD一起YY出来了一个游戏规则,规则如下. ...

  7. Java实现 LeetCode 96 不同的二叉搜索树

    96. 不同的二叉搜索树 给定一个整数 n,求以 1 - n 为节点组成的二叉搜索树有多少种? 示例: 输入: 3 输出: 5 解释: 给定 n = 3, 一共有 5 种不同结构的二叉搜索树: 1 3 ...

  8. LoadRunner性能测试笔试/面试题

    客户交付一个性能测试项目,请阐述你的实施流程. 测试设计阶段: 1)了解被测系统的性能需求,定义测试目标和范围: 2)了解系统的技术信息,如系统架构等: 3)确定测试方案.进度安排,并制定测试计划,场 ...

  9. 搞清楚C语言指针

    Part 0:为什么要写这篇文章 C语言中的指针是C语言的精髓,也是C语言的重难点之一. 然而,很少有教程能把指针讲的初学者能听懂,还不会引起歧义. 本文章会尝试做到这一点,如有错误,请指出. Par ...

  10. ElasticSearch系列之(一):介绍、安装(Docker、Windows、Linux)

    1.介绍 Elasticsearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口.Elasticsearch是用Java语言开发的,并 ...