本文始发于个人公众号: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. [leetcode] 并查集(Ⅱ)

    最长连续序列 题目[128]:链接. 解题思路 节点本身的值作为节点的标号,两节点相邻,即允许合并(x, y)的条件为x == y+1 . 因为数组中可能会出现值为 -1 的节点,因此不能把 root ...

  2. 利用Nginx设置跨域的方式

    1.服务端可控,添加响应头 2.服务端不可控.通过Nginx反向代理 3.服务端不可控.通过Nginx反向代理添加响应头 第一种方法.服务端可控时,可以在服务器端添加响应头(前端+后端解决) 浏览器地 ...

  3. Java分层经验

    在学习和使用Java的过程中,我们时常要用到各种工具与技术,它们在某些时候可以大幅度地简化编程,利用好它们,可以让代码更强壮.下面的表格是我总结的关于java开发可能会用到的工具与它们在项目中扮演的角 ...

  4. Angular 从入坑到挖坑 - 路由守卫连连看

    一.Overview Angular 入坑记录的笔记第六篇,介绍 Angular 路由模块中关于路由守卫的相关知识点,了解常用到的路由守卫接口,知道如何通过实现路由守卫接口来实现特定的功能需求,以及实 ...

  5. java方法句柄-----1.方法句柄类型、调用

    目录 方法句柄 1.方法句柄的类型 1.1MethodType类的对象实例的创建 1.1.1 通过指定参数和返回值的类型来创建MethodType.[显式地指定返回值和参数的类型] 1.1.2 通过静 ...

  6. Redis 单节点百万级别数据 读取 性能测试.

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 这里先进行造数据,向redis中写入五百万条数据,具体方式有如下三种: 方法一:(Lua 脚本) vim ...

  7. Java实现固定长度得01子串

    固定位数得01子串 Description 对于长度为n的一个01串,每一位都可能是0或1,一共有2 ^n 种可能.请按从小到大的顺序输出这2^n种01串. Input 包含多组数据,每组数据占一行, ...

  8. Java实现 LeetCode 211 添加与搜索单词 - 数据结构设计

    211. 添加与搜索单词 - 数据结构设计 设计一个支持以下两种操作的数据结构: void addWord(word) bool search(word) search(word) 可以搜索文字或正则 ...

  9. Java实现 LeetCode 66 加一

    66. 加一 给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一. 最高位数字存放在数组的首位, 数组中每个元素只存储单个数字. 你可以假设除了整数 0 之外,这个整数不会以零开头. 示 ...

  10. ntpq无法查询同步信息,显示The specified class was not found

    年初时工班发现工作站和服务器都没办法用ntpq看时钟同步了,如下图所示.输入ntpq-p 就显示"The specified class was not found" 通过排查,发 ...