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来表示目前正在遍历的元素。(免费图床质量太差,有空自己搭一个吧)

过程的描述(仅举部分例子):

  1. 从初始状态来看,nums[0]为0,nums[1]为1,两者不同,没有重复,故i++,j从i的下一位继续开始。

  2. num[1] = 2,num[2] = 2,重复!但此时i不要动,检查其他重复元素,直到出现不同元素为止。

    j++,num[3] = 3,不同,故i++,j从i的下一位继续开始。

  3. 重复以上过程,直到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——删除有序数组中的重复项(双指针法)的更多相关文章

  1. 【python】Leetcode每日一题-删除有序数组中的重复项

    [python]Leetcode每日一题-删除有序数组中的重复项 [题目描述] 给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 最多出现一次 ,返回删除后数组的新长度. 不要 ...

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

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

  3. 【python】Leetcode每日一题-删除有序数组中的重复项2

    [python]Leetcode每日一题-删除有序数组中的重复项2 [题目描述] 给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 最多出现两次 ,返回删除后数组的新长度. 不 ...

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

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

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

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

  6. 【LeetCode】26. 删除有序数组中的重复项

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

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

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

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

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

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

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

随机推荐

  1. 执行上下文与同步上下文 | ExecutionContext 和 SynchronizationContext

    原文连接:执行上下文与同步上下文 - .NET 并行编程 (microsoft.com) 执行上下文与同步上下文 斯蒂芬 6月15日, 2012 最近,我被问了几次关于 ExecutionContex ...

  2. mysql集群--基于centos7

    1 MySQL主从备份 主机:192.168.43.8 从机:192.168.43.6 条件:主机和从机都安装了mysql,开启了二进制日志 安装mysql (mysql 和 mysql-server ...

  3. node-java的使用及源码分析

    上篇文章简单提了下node调用java的方法但也只属于基本提了下怎么输出helloworld的层度,这次将提供一些案例和源码分析让我们更好地了解如何使用node-java库. 前置知识: 1.桥接模式 ...

  4. 用RecyclerView实现根据位置不同显示不同界面

    在原来的基础上将LinearAdapter.java进行修改: 1 public class LinearAdapter extends RecyclerView.Adapter<Recycle ...

  5. Linux的用户与用户组管理

    1.Linux用户与用户组 Linux 是多用户多任务操作系统,Linux 系统支持多个用户在同一时间内登陆,不同用户可以执行不同的任务,并且互不影响.不同用户具有不问的权限,毎个用户在权限允许的范围 ...

  6. JVM上篇:JVM与Java体系结构

    JVM笔记 JVM传言 Java不是最强大的语言,但是JVM是最强大的虚拟机 虚拟机分类 系统虚拟机 类似VMware,就属于系统虚拟机,它提供了一个可运行完整操作系统的平台 程序虚拟机 Java虚拟 ...

  7. TP5实现多文件上传及展示

    view层上传: <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...

  8. Objects.equals有坑

    前言 最近review别人代码的时候,发现有个同事,在某个业务场景下,使用Objects.equals方法判断两个值相等时,返回了跟预期不一致的结果,引起了我的兴趣. 原本以为判断结果会返回true的 ...

  9. 活用Windows Server 2008系统的几种安全功能

    与传统操作系统相比,Win2008系统的安全防范功能更加强大,安全防护能力自然也是高人一等,我们只要在平时善于使用该系统新增的各项安全防范功能,完全可以实现更高级别的安全保护目的.现在,本文就为大家贡 ...

  10. FrameScan-GUI CMS漏洞扫描

    工具简介 FrameScan-GUI是一款python3和Pyqt编写的具有图形化界面的cms漏洞检测框架,是FrameScan的加强版.支持多种检测方式,支持大多数CMS,可以自定义CMS类型及自行 ...