壹 ❀ 引

今天的题目来自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. C++数据结构(树)

    树是一种递归定义的数据结构,如果树中节点的各子树从左到右是有次序的,不能互换,则称该树为有序树,否则叫无序树. 关于树的节点: 节点拥有的子树的个数叫做节点的度 如果度为0,那么该节点叫做叶节点或终端 ...

  2. 基于python+django的求职招聘网站-网上招聘管理系统设计与实现

    该系统是基于python+django的求职招聘网站.网上招聘管理系统.网上人才招聘系统.毕业生求职招聘系统.大学生求职招聘系统.校园招聘系统.企业招聘系统.系统适合场景:大学生.课程作业.毕业设计. ...

  3. 02-VS调试以及Qt基本使用

    VS调试以及Qt基本使用 1.汇编语言 1.1 VS中C语言嵌套汇编代码(了解) #include <stdio.h> int main() { //定义整型变量a, b, c int a ...

  4. 有了Composition API后,有些场景或许你不需要pinia了

    前言 日常开发时有些业务场景功能很复杂,如果将所有代码都写在一个vue组件中,那个vue文件的代码量可能就几千行了,维护极其困难.这时我们就需要将其拆分为多个组件,拆完组件后就需要在不同组件间共享数据 ...

  5. http-长连接

    1. 短链接 http1.0 -- 1个请求-响应过程会创建且1个新的连接 2. 长连接 http1.1 -- 同域下可以创建1个tcp连接,多个请求在同一个tcp上串行处理请求 http2.0 -- ...

  6. [转帖]ORACLE新参数MAX_IDLE_TIME和MAX_IDLE_BLOCKING_TIME简介

    https://www.cnblogs.com/kerrycode/p/16856171.html Oracle 12.2 引入了新参数MAX_IDLE_TIME.它可以指定会话空闲的最大分钟数.如果 ...

  7. [转帖]使用 Logical Import Mode

    https://docs.pingcap.com/zh/tidb/v6.5/tidb-lightning-logical-import-mode-usage 配置及使用 可以通过以下配置文件使用 Lo ...

  8. [转帖]信创从芯开始,CPU实现国产有多难?

    https://www.eet-china.com/mp/a213516.html 数字底座的"底座"--CPU,决定信创底层逻辑的关键.CPU 是信息产业中最基础的核心部件,指令 ...

  9. 【转帖】text-davinci-003和ChatGPT之间的不同点

    https://zhuanlan.zhihu.com/p/603709081 先看下GPT的发展时间线 InstructGPT(2022 年 1 月)是一系列 GPT-3 模型(包括 text-dav ...

  10. [转帖]Linux块层技术全面剖析-v0.1

    Linux块层技术全面剖析-v0.1 perftrace@gmail.com 前言 网络上很多文章对块层的描述散乱在各个站点,而一些经典书籍由于更新不及时难免更不上最新的代码,例如关于块层的多队列.那 ...