Leetcode 删除有序数组中的重复项 Ⅱ
使用双指针来解决此问题,关键词“有序”数组,一个 index 指针用于构建新数组,一个 i 指针用于遍历整个数组
以下是代码的中文解释以及算法思想:
算法思想
这道题要求对一个有序数组进行去重,使得每个元素最多出现两次。我们需要在原数组上进行操作,不能使用额外的空间。为了实现这个要求,我们可以使用双指针法来完成:
-
初始化两个指针:
index
指针表示下一个可以插入的有效位置(用于构建结果数组),它初始值为 2,因为前两个元素无论如何都可以直接保留。i
指针遍历整个数组,从第三个元素开始检查(因为我们允许每个元素最多出现两次,所以不需要检查前两个元素)。
-
条件检查:
- 对于每个元素
nums[i]
,我们检查它是否等于nums[index - 2]
。如果不等,则表示nums[i]
至少可以插入到当前构建的结果数组中。 - 如果
nums[i] != nums[index - 2]
,则将nums[i]
放到nums[index]
位置上,并将index
指针向后移动一位,准备下一个位置。
- 对于每个元素
-
返回结果:
- 最终
index
的值就是新数组的长度,因为index
指针的值代表了有效数组的长度。 - 原数组前
index
个元素就是去重后的数组,且每个元素最多出现两次。
- 最终
代码示例
public class Solution {public int removeDuplicates(int[] nums) {if (nums.length <= 2) return nums.length;int index = 2; // 从第三个元素开始检查for (int i = 2; i < nums.length; i++) {// 如果当前元素 nums[i] 不等于 nums[index - 2],说明该元素可以加入if (nums[i] != nums[index - 2]) {nums[index] = nums[i];index++;}}return index;}
}
具体解释
- 数组长度小于等于 2:如果数组长度不超过 2,直接返回数组长度,因为每个元素都可以出现两次。
- 遍历数组:
- 从第三个元素开始(
i = 2
),逐个检查每个元素nums[i]
。 - 如果当前元素
nums[i]
不等于nums[index - 2]
,表示当前元素没有超过出现两次的限制。 - 将当前元素
nums[i]
放到nums[index]
位置上,然后将index
向后移动一位。
- 从第三个元素开始(
- 返回结果:
index
的值就是数组去重后的长度,数组的前index
个元素就是符合要求的结果。
复杂度分析
- 时间复杂度:O(n),因为我们只遍历了一遍数组。
- 空间复杂度:O(1),因为我们在原数组上进行操作,没有使用额外的空间。
示例
假设输入数组为 {1, 1, 1, 2, 2, 3}
:
- 初始状态:
index = 2
- 遍历:
i = 2
,nums[i] = 1
,nums[index - 2] = 1
,相等,跳过此元素。i = 3
,nums[i] = 2
,nums[index - 2] = 1
,不相等,将nums[i]
赋值给nums[index]
,index
增加 1。i = 4
,nums[i] = 2
,nums[index - 2] = 1
,不相等,将nums[i]
赋值给nums[index]
,index
增加 1。i = 5
,nums[i] = 3
,nums[index - 2] = 2
,不相等,将nums[i]
赋值给nums[index]
,index
增加 1。
- 最终结果:返回的长度
index = 5
,即{1, 1, 2, 2, 3}
java 代码如下:
class Solution {public int removeDuplicates(int[] nums) {// if (nums.length <= 2) return nums.length;int index = 2;for(int i = 2; i < nums.length; ++i) {if(nums[i] != nums[index - 2]) { //注意是index - 2, 而不是 i - 2nums[index++] = nums[i];}}return index;}
}
为什么这行代码的判断条件不是nums[i] != nums[i - 2]
if (nums[i] != nums[index - 2]) {
这是一个很好的问题。之所以判断条件写成 nums[i] != nums[index - 2]
而不是 nums[i] != nums[i - 2]
,是因为我们希望使用 index
指针来追踪构建新数组的有效长度,并确保每个元素最多出现两次。下面是具体原因:
原因解释
-
index
指针的作用:index
指针代表的是新数组的当前位置,也就是我们构建的、符合条件的数组的长度。index - 2
始终指向新数组的倒数第二个元素。因此,nums[index - 2]
可以用来判断当前的nums[i]
是否已经出现了两次。
-
避免原数组的重复元素影响判断:
- 如果直接用
nums[i - 2]
,它表示的是原数组的倒数第二个元素。然而,我们的目标是构建一个新的符合条件的数组,这个数组并不直接等同于原数组。 - 例如,在原数组中,某个元素可能已经出现多次,但在新数组(由
index
控制)中它可能只出现了一次。因此,判断条件需要使用nums[index - 2]
而不是nums[i - 2]
。
- 如果直接用
-
控制新数组的内容:
- 通过
nums[index - 2]
,我们可以确保只有符合条件的元素才被添加到新数组中,避免出现超过两次的重复。 - 如果使用
nums[i - 2]
,则我们判断的是原数组中的元素而不是新构建的数组,可能会导致多次重复的元素被错误地加入。
- 通过
举例说明
假设输入数组为 {1, 1, 1, 2, 2, 3}
:
-
初始时
index = 2
,我们从第三个元素(i = 2
)开始遍历。- 当
i = 2
时,nums[i] = 1
,如果我们使用nums[i - 2]
进行判断,那就是nums[0] = 1
。此时,它会与nums[i]
相等,判断条件为false
,意味着它会被加入到新数组中,导致1
出现三次,这是不符合题意的。 - 而使用
nums[index - 2]
(即nums[0] = 1
)作为判断条件时,我们可以正确地跳过这个元素,避免多余的重复。
- 当
通过使用 index
指针,我们有效地控制了新数组的内容,并保证每个元素最多出现两次。
相关文章:

Leetcode 删除有序数组中的重复项 Ⅱ
使用双指针来解决此问题,关键词“有序”数组,一个 index 指针用于构建新数组,一个 i 指针用于遍历整个数组 以下是代码的中文解释以及算法思想: 算法思想 这道题要求对一个有序数组进行去重,使得每个元素最多出现两…...
大模型学习笔记------什么是大模型
大模型学习笔记------什么是大模型 1、大模型定义2、大模型发展历程3、大模型的核心特点4、大模型的应用领域5、大模型面临的挑战6、结束语 近两年大模型超级火,并且相关产品迎来爆发式增长。在工作中,也常常接触到大模型,并且已经开始进行相…...

【unique_str 源码学习】
文章目录 1.删除器定义2. operator->() 运算符重载3. add_lvalue_reference<element_type>::type 使用 基本原理这篇博主写的很详细 https://yngzmiao.blog.csdn.net/article/details/105725663 1.删除器定义 deleter_…...

flask第一个应用
文章目录 安装一、编程第一步二、引入配置三、代码解析 安装 python环境安装的过程就不重复赘述了,flask安装使用命令pip install Flask即可,使用命令pip show Flask查看flask版本信息 提示:以下是本篇文章正文内容,下面案例可供…...

华为OD机试真题(Python/JS/C/C++)- 考点 - 细节
华为OD机试 2024E卷题库疯狂收录中,刷题 点这里。 本专栏收录于《华为OD机试真题(Python/JS/C/C)》。...
【C++刷题】力扣-#628-三个数的最大乘积
题目描述 给你一个整型数组 nums ,在数组中找出由三个数组成的最大乘积,并输出这个乘积。 示例 示例 1 输入:nums [1,2,3] 输出:6示例 2 输入:nums [1,2,3,4] 输出:24示例 3 输入:nums […...

Java项目实战II基于Java+Spring Boot+MySQL的工程教育认证的计算机课程管理平台(源码+数据库+文档)
目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者,专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 随着工程教…...

基于微信小程序实现信阳毛尖茶叶商城系统设计与实现
作者简介:Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验,被多个学校常年聘为校外企业导师,指导学生毕业设计并参与学生毕业答辩指导,…...

设计一个灵活的RPC架构
RPC架构 RPC本质上就是一个远程调用,需要通过网络来传输数据。传输协议可以有多种选择,但考虑到可靠性,一般默认采用TCP协议。为了屏蔽网络传输的复杂性,需要封装一个单独的数据传输模块用来收发二进制数据,这个单独模…...

大数据计算里的Broadcast Hash Join/Shuffle Hash Join/Sort Merge Join
文章目录 Broadcast Hash Join场景 Shuffle Hash Join场景 Sort Merge Join场景 Broadcast Hash Join 场景 大表和小小表,直接把B表加载到内存,然后读块1内容和内存中数据匹配 Shuffle Hash Join 场景 大表和小表JOIN ,小表分块后能加载…...

Java - 手写识别; 如何用spring ai和大模型做手写识别教程
识别后的文字 利用大模型提升Java手写识别:更简单、更高效 在Java场景中,我们经常需要处理手写识别的问题。过去,这类需求主要依赖于OCR技术,但其效果并不总是稳定。随着大模型的发展,使用大模型进行java手写识别成为…...

【Linux】用户权限管理:创建受限用户并配置特定目录访问权限
本文详细介绍了如何在 Linux 系统中创建一个名为 agent 的新用户,并限制其在特定目录下的权限。通过使用 useradd 命令创建用户,并使用 usermod 命令将新用户添加到现有用户组中,确保其具有适当的权限。接着,通过 chown 和 chmod …...
pgsql表分区和表分片设计
在设计 PostgreSQL 表分区和表分片时,主要目标是提高查询性能、可扩展性和数据管理的效率。以下是一些关键的设计步骤和策略: 1. 分区策略 水平分片:选择按日期进行水平分片,每天一个分片。这种策略适用于具有时间序列数据的场景…...

灵动AI ——视频创作新引擎 开启视觉奇幻之旅
灵动AI视频官网地址:https://aigc.genceai.com/ 灵动AI 科技与艺术的完美融合之作。它代表着当下最前沿的影像技术,为我们带来前所未有的视觉盛宴。...

AI设计、作图、画画工具哪个好用?看完这篇你就知道怎么选了
Stable Diffusion Stable Diffusion 是由 Stability AI 推出的开源 AI 文本到图像生成模型,以其开放性和灵活性在 AI 视觉工具领域广受欢迎。与 DALL-E 或 Midjourney 等只能依赖云计算的工具不同,Stable Diffusion 支持本地运行,也广泛兼容多…...

【python ASR】win11-从0到1使用funasr实现本地离线音频转文本
文章目录 前言一、前提条件安装环境Python 安装安装依赖,使用工业预训练模型最后安装 - torch1. 安装前查看显卡支持的最高CUDA的版本,以便下载torch 对应的版本的安装包。torch 中的CUDA版本要低于显卡最高的CUDA版本。2. 前往网站下载[Pytorch](https://pytorch.o…...
myqld二进制安装和破解数据库密码(linux)
安装和基本配置 1.首先把下载下来的mysql安装包放到本地这里下载的是5.7版本为演示 1)解压 tar xf mysql-5.7.20-linux-glibc2.12-x86_64.tar.gz -C /usr/local -把安装包解压到/usr/local cd /usr/local …...
防重方案-订单防重方案笔记
订单防重设计 订单重复提交概念解决方案前端防重机制后端防重机制利用Token机制基于数据库的唯一索引 Token机制方案介绍 其他 订单重复提交概念 重复提交指,连点按钮进行重复提交操作,不包括刷新后的重新下单,重新下单已非同一订单的概念。…...

HTML、JavaScript和CSS实现注册页面设计
目录 一、实现要求 二、实现页面图 1、注册页面 2.用户ID、用户名、口令验证成功后显示页面 三、用户ID、用户名、口令、确定口令验证逻辑js代码 1、验证用户ID 2、验证用户名 3、验证口令密码 四、总结 五、代码仓库 一、实现要求 综合使用HTML、JavaScript和CSS进…...
Counter对象的使用样例
1. Counter类的定义和功能说明 Counter是一个用于跟踪值出现次数的有序集合。它可以接收一个可迭代对象作为参数,并生成一个字典,其中包含每个元素作为键,其计数作为值。 2. 统计列表或字符串中元素的出现次数 示例代码: from…...

接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...

技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的
修改bug思路: 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑:async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...
学习一下用鸿蒙DevEco Studio HarmonyOS5实现百度地图
在鸿蒙(HarmonyOS5)中集成百度地图,可以通过以下步骤和技术方案实现。结合鸿蒙的分布式能力和百度地图的API,可以构建跨设备的定位、导航和地图展示功能。 1. 鸿蒙环境准备 开发工具:下载安装 De…...

【堆垛策略】设计方法
堆垛策略的设计是积木堆叠系统的核心,直接影响堆叠的稳定性、效率和容错能力。以下是分层次的堆垛策略设计方法,涵盖基础规则、优化算法和容错机制: 1. 基础堆垛规则 (1) 物理稳定性优先 重心原则: 大尺寸/重量积木在下…...

内窥镜检查中基于提示的息肉分割|文献速递-深度学习医疗AI最新文献
Title 题目 Prompt-based polyp segmentation during endoscopy 内窥镜检查中基于提示的息肉分割 01 文献速递介绍 以下是对这段英文内容的中文翻译: ### 胃肠道癌症的发病率呈上升趋势,且有年轻化倾向(Bray等人,2018&#x…...