数组(一)-- LeetCode[26][80] 删除有序数组中的重复元素

news2025/7/16 0:40:23

1 删除有序数组中的重复项

1.1 题目描述

        给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致

        由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。

        将最终结果插入 nums 的前 k 个位置后返回 k 。

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

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

1.2 思路分析

        已知数组 nums 是有序的,而且我们只能在原地修改 nums 数组,不能创建新的数组空间来存储删除重复出现的元素后的结果。我们需要一边遍历数组查找相同元素,一边在对比发现不同元素时修改数组元素,那么我们可以考虑双指针法的快慢指针了,定义 p 和 q 作为指针,初始化时指针 p 指向数组的起始位置(nums[0]),指针 q 指向指针 p 的后一个位置(nums[1])。随着指针 q 不断向后移动,将指针 q 指向的元素与指 p 指向的元素进行比较:

  • 如果nums[q] ≠ nums[p],那么nums[p + 1] = nums[q];
  • 如果nums[q] = nums[p],那么指针q继续向后查找;

图示:

1.3 代码实现

class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        p, q = 0, 1
        while q < len(nums):
            if nums[q] != nums[p]:
                p += 1
                nums[p] = nums[q]
            q += 1
        
        return p + 1

        复杂度分析:时间复杂度: O ( n ) O(n) O(n)。 空间复杂度: O ( 1 ) O(1) O(1)

        进一步优化:

        考虑如下数组:

        此时数组中没有重复元素,按照上面的方法,每次比较时 nums[p] 都不等于 nums[q],因此就会将 q 指向的元素原地复制一遍,这个操作其实是不必要的。

        因此我们可以添加一个小判断,当 q - p > 1 时,才进行复制。

class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        p, q = 0, 1
        while q < len(nums):
            if nums[q] != nums[p]:
                if q - p > 1:
                    nums[p+1] = nums[q]
                p += 1
            q += 1
        
        return p + 1

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

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

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

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

        思路和上面的类似,改变的地方是:初始化时指针 p 指向数组的起始位置(nums[1]),指针 q 指向指针 p 的后一个位置(nums[2])。随着指针 q 不断向后移动,将指针 q 指向的元素与指 p 指向的元素进行比较:

  • 如果nums[q] ≠ nums[p-1],那么nums[p + 1] = nums[q];
  • 如果nums[q] = nums[p],那么指针q继续向后查找;
```python
class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        p, q = 1, 2
        while q < len(nums):
            if nums[q] != nums[p-1]:
                p += 1
                nums[p] = nums[q]
            q += 1
        
        return p + 1

通用解法:
        为了让解法更具有一般性,我们将原问题的「最多保留 1 位」修改为「最多保留 k 位」。
对于此类问题,我们应该进行如下考虑:

  • 由于是保留 k 个相同数字,对于前 k 个数字,我们可以直接保留。
  • 对于后面的任意数字,能够保留的前提是:与当前写入的位置前面的第 k 个元素进行比较,不相同则保留。

        此时,初始化时指针 p 指向数组的起始位置(nums[k-1]),指针 q 指向指针 p 的后一个位置(nums[k])。随着指针 q 不断向后移动,将指针 q 指向的元素与指 p 指向的元素进行比较:

  • 如果nums[q] ≠ nums[p-k+1],那么nums[p + 1] = nums[q];
  • 如果nums[q] = nums[p],那么指针q继续向后查找;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/361421.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

FreeRTOS与UCOSIII任务状态对比

FreeRTOS任务状态 1、运行态 正在运行的任务&#xff0c;正在使用处理器的任务。 单核处理器中任何时候都有且只有一个任务处于运行态。 2、就绪态 已经准备就绪&#xff08;非阻塞或挂起&#xff09;&#xff0c;可以立即运行但还没有运行的任务。 正在等待比自己高优先级…

Kafka——消息队列学习总结

定义 Kafka是一个分布式的基于发布/订阅模式的消息队列&#xff08;MQ)&#xff0c;主要应用于大数据实时处理领域。 模式 点对点模式 一对一&#xff0c;消费者主动拉取数据&#xff0c;消费收到后消息清除。 发布/订阅模式 一对多&#xff0c;消费者消费数据后不会清除消息…

JavaScript:使用for in不是一个很好的抉择

for in 如果让你遍历对象中的key和value&#xff0c;你第一个想到的一定是使用for in const o{name:"chengqige",age:23 } for (let key in o){console.log(key,o[key]); }看起来是没有问题的&#xff0c;但是如果我在下面加一行代码&#xff0c;输出的结果就可能让…

JUC并发编程——进程与线程

目录一、进程和线程的概念1.1 进程1.2 线程1.3 进程与线程对比二、并行和并发的概念三、线程基本应用3.1 多线程应用——异步调用一、进程和线程的概念 1.1 进程 ● 程序由指令和数据组成&#xff0c;但这些指令要运行&#xff0c;数据要读写&#xff0c;就必须将指令加载至 …

内容生态与新业务双突破,汽车之家反转逻辑将延续

2022年&#xff0c;疫情对汽车市场的影响不容忽视。但从财报来看&#xff0c;汽车之家在宏观压力下仍实现了有力的V型反转。 北京时间2月16日美股盘前&#xff0c;汽车之家发布2022Q4及全年财报。财报显示&#xff0c;其四季度实现总营收18.93亿元&#xff0c;同比增长11.8%。…

java并发笔记

文章目录HashMapput方法resize方法ConcurrentHashMapput方法initTable方法sizectl代表什么&#xff1a;扩容计数器ConcurrentHashMap的读操作会阻塞嘛AQS唤醒线程时&#xff0c;AQS为什么从后往前遍历&#xff1f;AQS为什么要有一个虚拟的head节点AQS为什么用双向链表&#xff…

无线网络渗透测试系列学习(一) - 在Windows系统下使用虚拟机安装Kali Linux操作系统

目录 引言&#xff1a; 过程&#xff1a; 配置以及安装VMware虚拟机&#xff1a; 下载Kali Linux的镜像文件&#xff1a; 在虚拟机中打开Kali Linux并执行安装&#xff1a; 配置Kali Linux操作系统&#xff1a; 调整Kal Linux中的时区&#xff1a; 重新设定管理员root的…

Sketch+摹客,100M文件上传最快47s

哈喽&#xff0c;小摹来啦~ 去年12月底&#xff0c;摹客Sketch插件上新了「规范检查工具」&#xff0c;自功能上线以来&#xff0c;小摹收到了许多的好评及赞扬。 虽好评如潮&#xff0c;但我们不会止步不前&#xff0c;将持续攻克难点&#xff0c;旨在为大家提供更加稳定高效…

考公和大厂40万年薪的offer,选哪个?

眼看毕业将至&#xff0c;相信很多小伙伴已经摩拳擦掌&#xff0c;在为毕业季就业做准备了。2023年高校毕业生规模预计1158万人&#xff0c;同比增加82万人。在资深人力资源服务家汪张明看来&#xff0c;2023年的就业态势不仅是大学毕业生数量有增加&#xff0c;还存在一定的存…

开发一个简单易用的SDK的详细步骤(超详细,超适用)

文章目录开发一个简单易用的SDK的详细步骤创建starter步骤关键点总结开发一个简单易用的SDK的详细步骤 创建starter步骤 1.新建一个 spring boot 初始化项目 2.添加依赖&#xff0c;Lombok, Spring Configuration Processor Spring Configuration Processor 的作用是自动生…

2023.2 新方案 java代码混淆 java加密 字符串加密

Java字节码可以反编译&#xff0c;特别是创业公司,很好的项目很容易被别人破解反编译,造成很严重的损失,所以本混淆方案能很好的保护源码,而且在不断迭代,增强混淆效果,异常问题处理,达到保护项目的目的&#xff1a; 本次升级包括: 2023年02年19日 : ht-confusion-project-1.8…

华为云计算之双活容灾

双活&#xff08;HyperMetro&#xff09;本地双活&#xff1a;距离≤10km同城双活&#xff1a;距离&#xff1e;10km没有主备之分&#xff0c;只有本端数据中心和远端数据中心。当一个数据中心的设备故障或数据中心故障&#xff0c;业务会自动切换到另一个数据中心继续运行&…

17_FreeRTOS事件标志组

目录 事件标志组 事件标志组与队列、信号量的区别 事件标志组相关API函数介绍 实验源码 事件标志组 事件标志位:用一个位,来表示事件是否发生 事件标志组是一组事件标志位的集合,可以简单的理解事件标志组,就是一个整数。 事件标志组的特点: 它的每一个位表示一个事件(…

如何效率搭建企业流程系统?试试低代码平台吧

编者按&#xff1a;本文介绍了一款可私有化部署的低代码平台&#xff0c;可用于搭建团队流程管理体系&#xff0c;并详细介绍了该平台可实现的流程管理功能。关键词:可视化设计&#xff0c;集成能力&#xff0c;流程审批&#xff0c;流程调试天翎是国内最早从事快速开发平台研发…

Vscode创建vue项目的详细步骤

目录 一、概述 操作的前提 二、操作步骤 一、概述 后端人员想在IDEA里面创建一个Vue的项目&#xff0c;但是这非常麻烦&#xff0c;用vscode这个前端专用软件创建就会非常快速。 操作的前提 1.安装vscode软件的步骤&#xff1a;vscode下载和安装教程和配置中文插件&#…

分析JEP 290机制的Java实现

简介 https://openjdk.org/jeps/290 Filter Incoming Serialization Data过滤传入的序列化数据 JEP290是Java官方提供的一套来防御反序列化的机制&#xff0c;其核心在于提供了一个ObjectInputFilter接口&#xff0c;通过设置filter对象&#xff0c;然后在反序列化&#xff…

springcloud+vue实现图书管理系统

一、前言&#xff1a; 今天我们来分享一下一个简单的图书管理系统 我们知道图书馆系统可以有两个系统&#xff0c;一个是管理员管理图书的系统&#xff0c;管理员可以&#xff08;1&#xff09;查找某一本图书情况、&#xff08;2&#xff09;增加新的图书、&#xff08;3&…

Python+Selenium4三大等待预期条件_web自动化(4)

目录 0. 上节回顾 1. 定位失败的原因 2. 强制等待 3. 隐式等待 4. 显式等待 【重点难点】 4.1. 实例化 WebDriverWait 对象 4.2. 指定等待条件 4.3. 等待条件的具体要求 4.3. 1. 等待条件是一个函数 4.3. 2. 返回值是布尔值 4.3. 3. 只有一个参数&#xff0c;参数值…

查询服务器tns文件路径,oracle数据库tns配置方法详解

查询服务器tns文件路径,oracle数据库tns配置方法详解 TNS简要介绍与应用 Oracle中TNS的完整定义&#xff1a;transparence Network Substrate透明网络底层&#xff0c; 监听服务是它重要的一部分&#xff0c;不是全部&#xff0c;不要把TNS当作只是监听器。 TNS是Oracle Net…

scrum敏捷开发实践—leangoo任务看板

任务板展现了我们在Sprint过程中所有要完成的任务。在Sprint过程中我们要不断的更新它。–如果某个开发人员想到了一个任务他就可以把这个任务写下来放在任务墙上。无论每日站会过程中或者之后&#xff0c;如果估计发生了变化&#xff0c;任务会根据变化在任务墙上做相应的调整…