壹 ❀ 引

今天的题目来自LeetCode80. 删除有序数组中的重复项 II,是一道难度中等,但实际挺简单的一道题,题目描述如下:

给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 最多出现两次 ,返回删除后数组的新长度。

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

说明:

为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

你可以想象内部操作如下:

// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
int len = removeDuplicates(nums); // 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。
for (int i = 0; i < len; i++) {
print(nums[i]);
}

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

  • 1 <= nums.length <= 3 * 104
  • -104 <= nums[i] <= 104
  • nums 已按升序排列

贰 ❀ 简单分析,按题意硬解

我们简单提取下题目信息,给定一个升序排列的数组,要求在经过处理过,数组中连续的重复的数字最多不超过两个,题目要求不能使用额外数组,我们必须原地修改数组。

当看到这,我的第一感觉就是使用计数,统计一个数字出现的次数,如果出现次数少于2之前,我们可以继续往后找,而当超过2次时就需要剔除掉当前元素,完整遍历一次后自然就是我们想要的结果了。

当然,我想到这就开始写代码了,然后写出了如下笨比代码,当然也通过了:

/**
* @param {number[]} nums
* @return {number}
*/
var removeDuplicates = function (nums) {
//用于记录数字出现的次数
let map = {};
// 记录相同数字出现的次数,超过2删除掉
for (let i = 0; i < nums.length;) {
// 第一次出现时
if (map[nums[i]] === undefined) {
map[nums[i]] = 1;
i++;
// 记录多次时要判断有没有超过2
} else if (map[nums[i]] + 1 > 2) {
nums.splice(i,1);
}else{
map[nums[i]] = map[nums[i]]+1;
i++;
};
};
return nums.length;
};

上面代码思路其实是对的,只是一时半会还没完成理清,就有点硬编码的意思,下面这段代码是在看了题解后,重新整理的逻辑,思路与上方代码相同:

/**
* @param {number[]} nums
* @return {number}
*/
var removeDuplicates = function (nums) {
// 根据题意,至少有一个元素
let s = 1;
// 因此遍历从1开始
let i = 1;
while (i < nums.length) {
// 比如,第二个跟第一个还相同,应该让s加1,但需要考虑的是,超出了2了怎么办
if (nums[i] === nums[i - 1]) {
if (s === 2) {
nums.splice(i, 1);
} else {
i++;
s++;
}
} else {
// 如果不相等,说明遇到了不同的元素了,重置mark
s = 1;
i++;
}
}
};

唯一有点区别的是,上述代码使用了一个数字用于单独记录相同数字出现的次数,而非我前面使用对象一一去记录。

叁 ❀ 快慢双指针

在题目实例说明中,其实特意强调了一句不需要考虑数组中超出新长度后面的元素,什么意思呢,比如如下数组:

[1,1,1,2,2,3]
//经过某种处理可以转变成
[1,1,2,2,3,3]

也就是说,因为期望的答案是[1,1,2,2,3],而上面转变后的数组,前五个也满足预期答案,超出的部分可以不用考虑,也因为如此,才支撑了接下来的解法。

我们已知数组中数字最多不超过2个,也就是,不管给定一个什么数组,前2位一定是合格的,比如[1,2]或者[1,1],真正需要考虑的元素应该是从第三位开始。

我们可以定义快慢两个指针,快指针总是从头到尾遍历,而慢指针,当遇到超出三个的时候就停下来,让快指针继续搜索,直到遇到不相同的元素了,就替换掉慢指针所在元素,如果成功替换,慢指针进一位,说起来可能有点模糊,我们先看代码:

/**
* @param {number[]} nums
* @return {number}
*/
var removeDuplicates = function(nums) {
// 这里做了通用,比如题目说最多三个相同,这里就传递3
return process(nums, 2)
}; function process(nums, k) {
// 这里的s就是慢指针
let s = 0
// 这里的i是快指针
for (let i=0;i<nums.length;i++) {
// s<k是因为前k个数字一定不会不满足条件,满足前者即可
if (s < k || nums[s - k] !== nums[i]) {
nums[s] = nums[i]
s++;
};
};
return s;
}

慢指针s与快指针i初始都是0,根据提议,前2个数字一定满足条件,因此才有s<k,所以前两次循环因为s<k满足,后面的条件就不会比较,直接更新两次慢指针的数字,并让慢指针右移动。

从第三次比较开始,nums[s - k]也就是nums[2 - 2]与快指针的nums[i]相同,此时i已经是3了,这说明已经超出了最多2个的范围了,怎么办?当然是不做操作,快指针i继续往后跑,直到遇到nums[s - k] !== nums[i]的数字,说明可以用不同的数字对刚才慢指针所在的数字进行替换了,一直到快指针遍历完成,原数组中所有数字都会满足最多不超过2个的情况。

其实今天还是有点累了,就偷个懒不画图了,如果这里比较难理解,可以断点跟一下代码,自己尝试画图理一理,那么就先记录到这里了。

JS Leetcode 80. 删除有序数组中的重复项 II题解,常规解法与快慢双指针做法的更多相关文章

  1. [LeetCode每日一题]80. 删除有序数组中的重复项 II

    [LeetCode每日一题]80. 删除有序数组中的重复项 II 问题 给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 最多出现两次 ,返回删除后数组的新长度. 不要使用额外 ...

  2. 【LeetCode】80. 删除有序数组中的重复项 II

    80. 删除有序数组中的重复项 II 知识点:数组:排序:双指针: 题目描述 给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 最多出现两次 ,返回删除后数组的新长度. 不要使 ...

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

    题目 给你一个有序数组 nums ,请你原地删除重复出现的元素(不需要考虑数组中超出新长度后面的元素),使每个元素最多出现两次 ,返回删除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入 ...

  4. LeetCode 80. 删除排序数组中的重复项 II

    LeetCode 80. 删除排序数组中的重复项 II

  5. Java实现 LeetCode 80 删除排序数组中的重复项 II(二)

    80. 删除排序数组中的重复项 II 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O ...

  6. 4.19——数组双指针——26. 删除有序数组中的重复项 & 27. 删除有序数组中的重复项II & 80. 删除有序数组中的重复项 II

    第一次做到数组双指针的题目是80: 因为python的List是可以用以下代码来删除元素的: del List[index] 所以当时的我直接用了暴力删除第三个重复元素的做法,大概代码如下: n = ...

  7. Leetcode 80.删除排序数组中的重复项 II By Python

    给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成. 示例 ...

  8. LeetCode 80. 删除排序数组中的重复项 II(Remove Duplicates from Sorted Array II)

    题目描述 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成 ...

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

    题目描述 给你一个有序数组 nums ,请你原地删除重复出现的元素,使每个元素最多出现两次,返回删除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组 并在使用O(1)额外空间的条件下 ...

  10. [LeetCode]26.删除有序数组中的重复项(Java)

    原题地址: remove-duplicates-from-sorted-array 题目描述: 给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的 ...

随机推荐

  1. Liunx运维(二)-文件与目录操作

    文档目录: 一.pwd:显示当前位置 二.cd:切换目录 三.tree:树形结构显示目录 四.mkdir 创建目录 五.touch:创建空文件或改变文件时间戳 六.ls:显示目录下内容相关属性信息 七 ...

  2. Cortex-M3内核介绍

    目录 Cortex Vendor - ARM介绍 ARM主要提供指令集,需要授权 ARM使用的RSIC结构,功耗比较低 Cortex M3整体架构 核心是Processor Core - 包含寄存器和 ...

  3. 【linux】Linux内核结构体--kfifo 环状缓冲区

    1.前言 最近项目中用到一个环形缓冲区(ring buffer),代码是由linux内核的kfifo改过来的.缓冲区在文件系统中经常用到,通过缓冲区缓解cpu读写内存和读写磁盘的速度.例如一个进程A产 ...

  4. VMware虚拟机部署Linux Ubuntu系统的方法

      本文介绍基于VMware Workstation Pro虚拟机软件,配置Linux Ubuntu操作系统环境的方法.   首先,我们需要进行VMware Workstation Pro虚拟机软件的 ...

  5. 【面试题精讲】Mysql如何实现乐观锁

    有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top 首发博客地址 文章更新计划 系列文章地址 在 MySQL 中,可以通过使用乐 ...

  6. [转帖]没 K8s 用不了 Chaos Mesh?试试 Chaosd

    https://cn.pingcap.com/blog/cannot-use-chaosmesh-without-k8s-then-try-chaosd Chaosd 是什么? 相信大家对 Chaos ...

  7. [转帖]MinIO系列7 - Minio性能压测

    https://www.zhihu.com/people/keen-wang 前言 声明:此文为本人历史笔记的整理,文章实际撰写时间为2021年2月份,所以本中所使用的相关组件版本较老.此文是通过压力 ...

  8. [转帖]linux内存挂载

    1.主要功能 在linux中,为了提高读写速度,可以将内存挂载到目录,常见的文件格式有tmpfs和ramfs. 2.挂载步骤 $ sudo mkdir /mnt/tmp $ sudo mkdir /m ...

  9. 【转帖】10个Linux 系统性能监控命令行工具

    引言: 系统一旦跑起来,我们就希望它能够稳定运行,不要宕机,不出现速度变慢.因此,对于Linux 系统管理员来说每天监控和调试 Linux 系统的性能问题是一项繁重却又重要的工作.监控和保持系统启动并 ...

  10. 查看dmesg 里面部分内容的精确时间

    for i in `dmesg |grep "stuck for" |awk '{print $1}' |awk -F "." '{print $1}' |aw ...