Leetcode26——删除有序数组中的重复项(双指针法)
Leetcode26——删除有序数组中的重复项(双指针法)
1. 题目简述
给你一个升序排列的数组 nums ,请你原地 删除重复出现的元素,使每个元素只出现一次 ,返回删除后数组的新长度。元素的相对顺序 应该保持一致 。
由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。
将最终结果插入 nums 的前 k 个位置后返回 k 。
不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
判题标准:
系统会用下面的代码来测试你的题解:
int[] nums = [...]; // 输入数组
int[] expectedNums = [...]; // 长度正确的期望答案
int k = removeDuplicates(nums); // 调用
assert k == expectedNums.length;
for (int i = 0; i < k; i++) {
assert nums[i] == expectedNums[i];
}
如果所有断言都通过,那么您的题解将被 通过。
示例 1:
输入:nums = [1,1,2]
输出:2, nums = [1,2,_]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。
示例 2:
输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]
解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。
提示:
0 <= nums.length <= 3 * 104
-104 <= nums[i] <= 104
nums 已按 升序 排列
(原题链接:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/)
2. 暴力破解法
最简单的想法应该是使用暴力破解法,即使用两层循环,如遇到下标为i + 1的元素与下标为i的元素相同,则将后面的元素依次覆盖到到前一个位置,否则自增内层变量j。此外,用一个变量来记录数组在覆盖元素后的新长度,即初始值为数组长,每次覆盖该变量减少1。
虽然思路非常简单,但是有一个容易出错的地方:这里内层最好是使用while循环,这与我们覆盖的方式有关。覆盖之后,内层循环变量不能加1!否则会越过一个元素哦!也就是说无法完全消除重复的元素。
class Solution {
public int removeDuplicates(int[] nums) {
int newLength = nums.length;
int j;
for (int i = 0; i < newLength; i++) {
j = i + 1;
while (j < newLength) {
if (nums[i] == nums[j]) {
for (int k = j + 1; k < newLength; k++) {
nums[k-1] = nums[k];
}
newLength--;
}
else
j++;
}
}
return newLength;
}
}
代码分析
这个思路非常直接,但是代价是数组去重时会移动大量的元素,这造成了相当程度上资源的浪费。
3. 双指针法
该如何解决暴力解法的问题呢?可见我们要尽可能降低数组元素移动的次数(也就是数组的覆盖去重操作)。
让我们仔细阅读一下题目,我们只要保证处理后的数组前k个元素是不重复且相对顺序不变的即可,我们可以拿一个整型变量i来表示处理后数组各个位置的数组下标,拿另一个整型变量j来表示目前正在遍历的元素。(免费图床质量太差,有空自己搭一个吧)

过程的描述(仅举部分例子):
从初始状态来看,nums[0]为0,nums[1]为1,两者不同,没有重复,故i++,j从i的下一位继续开始。
num[1] = 2,num[2] = 2,重复!但此时i不要动,检查其他重复元素,直到出现不同元素为止。
j++,num[3] = 3,不同,故i++,j从i的下一位继续开始。
重复以上过程,直到j指针到数组末端
class Solution {
public int removeDuplicates(int[] nums) {
int i = 0, j = 1;
while (j < nums.length) {
if (nums[i] != nums[j]) {
i++;
nums[i] = nums[j];
}
else
j++;
}
return i + 1; // 返回的是无重复数组长哦
}
}
代码分析
由于在运行的过程中,每个元素最多被访问两次,最坏情况时间复杂度为O(n),这是一个非常大的提升了!这也是我自己第一次悟出来双指针法!纪念一下!
Leetcode26——删除有序数组中的重复项(双指针法)的更多相关文章
- 【python】Leetcode每日一题-删除有序数组中的重复项
[python]Leetcode每日一题-删除有序数组中的重复项 [题目描述] 给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 最多出现一次 ,返回删除后数组的新长度. 不要 ...
- [LeetCode每日一题]80. 删除有序数组中的重复项 II
[LeetCode每日一题]80. 删除有序数组中的重复项 II 问题 给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 最多出现两次 ,返回删除后数组的新长度. 不要使用额外 ...
- 【python】Leetcode每日一题-删除有序数组中的重复项2
[python]Leetcode每日一题-删除有序数组中的重复项2 [题目描述] 给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 最多出现两次 ,返回删除后数组的新长度. 不 ...
- 删除有序数组中的重复项II
题目描述 给你一个有序数组 nums ,请你原地删除重复出现的元素,使每个元素最多出现两次,返回删除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组 并在使用O(1)额外空间的条件下 ...
- 【LeetCode】80. 删除有序数组中的重复项 II
80. 删除有序数组中的重复项 II 知识点:数组:排序:双指针: 题目描述 给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 最多出现两次 ,返回删除后数组的新长度. 不要使 ...
- 【LeetCode】26. 删除有序数组中的重复项
26. 删除有序数组中的重复项 知识点:数组:排序:双指针: 题目描述 给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度. 不要使用额外的 ...
- 80. 删除有序数组中的重复项 II
题目 给你一个有序数组 nums ,请你原地删除重复出现的元素(不需要考虑数组中超出新长度后面的元素),使每个元素最多出现两次 ,返回删除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入 ...
- 4.19——数组双指针——26. 删除有序数组中的重复项 & 27. 删除有序数组中的重复项II & 80. 删除有序数组中的重复项 II
第一次做到数组双指针的题目是80: 因为python的List是可以用以下代码来删除元素的: del List[index] 所以当时的我直接用了暴力删除第三个重复元素的做法,大概代码如下: n = ...
- [LeetCode]26.删除有序数组中的重复项(Java)
原题地址: remove-duplicates-from-sorted-array 题目描述: 给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的 ...
随机推荐
- 【windows 操作系统】Windows系统机制之对象管理器
转载自 Windows系统机制之对象管理器 设计的几个目的: 提供一种公共统一的机制来使用系统资源 将对象保护隔离到OS中的一个地方,从而确保统一的一致的对象访问策略 提供一种机制来管理进程对对象的使 ...
- 3rd S-curve velocity profile
3rd S-curve (1) (2) (3) (4) 完整的三次S曲线包括上面的七个阶段.前面三个阶段为加速阶段,从初始速度Vs加速到Vmax: (5) 整个加速阶段的位移为: (6) 后面三个阶 ...
- python学习笔记:1、读取文本文件,按行处理
需求源于 整理 时序报告.按照以前的思路 都是按行行的 进行处理 提取需要的信息,判断. 首先的操作应该是读取. python的读取 两个方法 (1) 通过readline()来进行读取 f = op ...
- pandas模块篇(之三)
今日内容概要 目标:将Pandas尽量结束 如何读取外部excel文件数据到DataFrame中 针对DataFrame的常用数据操作 索引与切片 操作DataFrame的字段名称 时间对象序列操作 ...
- zookeeper的JAVA API使用
1.创建连接 2.创建节点 3.监听信息 Watcher.class 4.获取节点 Stat stat = new Stat(); zk.getData(Path,true,stat); 5.修改节点 ...
- javascript订阅模式浅析和基础实例
前言 最近在开发redux或者vux的时候,状态管理当中的createStore,以及我们在组件中调用的dispatch传递消息给状态管理中心,去处理一些操作的时候,有些类似我们常见到订阅模式 于是写 ...
- 打靶笔记-01-vulnhub-moneybox
打靶笔记-01-vulnhub-moneybox 本篇笔记根据苑老师视频进行学习记录 https://www.bilibili.com/video/BV1Lv411n7Lq/?spm_id_from= ...
- docker学习笔记(3)- 镜像
简介 在docker学习笔记(1)- 架构概述一节中可以看到镜像是docker三大组件之一,可以将Docker镜像类比为虚拟机的模版. 镜像由多个层组成,每层叠加之后从外部看就像一个独立的对象,镜像的 ...
- CF698C题解
为什么 \(n,k \leq 20\)? 我还以为是什么 \(n,k \leq 10^6\) 的厉害题/qd 看到这个队列操作很迷惑,但是仔细看看要操作 \(10^{100}\) 遍,所以我们可以直接 ...
- C#解析Markdown文档,实现替换图片链接操作
前言 又是好久没写博客了 其实也不是没写,是最近在「做一个博客」,从2月21日开始,大概一个多星期的时间,疯狂刷进度,边写代码边写了一整系列的博客开发笔记,目前为止已经写了16篇了,然后上3月之后工作 ...