当前位置: 首页 > article >正文

【LeetCode刷题日记】1047:双栈法与双指针法巧妙消除相邻重复字符

个人主页北极的代码欢迎来访作者简介java后端学习者❄️个人专栏苍穹外卖日记SSM框架深入JavaWeb✨命运的结局尽可永在不屈的挑战却不可须臾或缺摘要本文针对LeetCode 1047题删除字符串中的所有相邻重复项提出了两种解法。第一种使用Deque栈结构通过压栈和弹栈操作消除相邻重复字符最后反转剩余字符得到结果。第二种采用双指针法将原数组模拟为栈通过快慢指针实现原地修改空间效率更高。两种方法的时间复杂度均为O(n)但双指针法将空间复杂度优化至O(1)。文章详细分析了两种实现的核心逻辑、性能差异和适用场景并提供了完整的Java代码实现。题目背景LeetCode1047给出由小写字母组成的字符串 S重复项删除操作会选择两个相邻且相同的字母并删除它们。在 S 上反复执行重复项删除操作直到无法继续删除。在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。示例输入abbaca输出ca解释例如在 abbaca 中我们可以删除 bb 由于两字母相邻且相同这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 aaca其中又只有 aa 可以执行重复项删除操作所以最后的字符串为 ca。提示1 S.length 20000S 仅由小写英文字母组成。题目解析第一种解法Deque栈实现本题要删除相邻相同元素相对于20. 有效的括号 来说其实也是匹配问题20. 有效的括号 是匹配左右括号本题是匹配相邻元素最后都是做消除的操作。本题也是用栈来解决的经典题目。那么栈里应该放的是什么元素呢我们在删除相邻重复项的时候其实就是要知道当前遍历的这个元素我们在前一位是不是遍历过一样数值的元素那么如何记录前面遍历过的元素呢所以就是用栈来存放那么栈的目的就是存放遍历过的元素当遍历当前的这个元素的时候去栈里看一下我们是不是遍历过相同数值的相邻元素。然后再去做对应的消除操作。 如动画所示然后从栈中弹出剩余元素此时是字符串ac因为从栈里弹出的元素是倒序的所以再对字符串进行反转一下就得到了最终的结果。text遍历字符串 abbaca 步骤1: 栈空 → 压入 a 栈: [a] 步骤2: b ≠ 栈顶a → 压入 b 栈: [a, b] 步骤3: b 栈顶b → 弹出 b 栈: [a] ← 发现重复消除 步骤4: a 栈顶a → 弹出 a 栈: [] ← 发现重复消除 步骤5: c ≠ 栈顶(空) → 压入 c 栈: [c] 步骤6: a ≠ 栈顶c → 压入 a 栈: [c, a] 输出: 栈中剩余 [c, a] → 反转得到 ca代码实操我们先要实现栈我们这里使用Deque来实现栈ArrayDeque会比LinkedList在除了删除元素这一点外会快一点为什么用 ArrayDeque 而不是 LinkedList特性ArrayDequeLinkedList底层结构循环数组双向链表内存占用更小更大每个节点有前后指针随机访问O(1)O(n)插入/删除O(1)均摊O(1)CPU 缓存友好✅ 是❌ 否结论对于栈操作只在一端插入删除ArrayDeque 性能更好。接下来的判断当栈是空的时候或者栈顶的元素跟我们遍历的元素不相等时入栈如果栈顶跟我们遍历的元素相等时出栈则消除了重复的元素。逻辑分支表条件动作含义deque.isEmpty()push(ch)第一个字符无物可消deque.peek() ! chpush(ch)不同字符暂存等待deque.peek() chpop()相同字符互相抵消之后把结果进行反转text栈底 → 栈顶 [c, a] (a 是栈顶) pop() 顺序先取 a再取 c 如果直接拼接str a c ac ❌ 错误 正确做法str pop() str - 第一次str a a - 第二次str c a ca ✅题目答案使用 Deque 作为堆栈class Solution { public String removeDuplicates(String S) { //ArrayDeque会比LinkedList在除了删除元素这一点外会快一点 //参考https://stackoverflow.com/questions/6163166/why-is-arraydeque-better-than-linkedlist ArrayDequeCharacter deque new ArrayDeque(); char ch; for (int i 0; i S.length(); i) { ch S.charAt(i); if (deque.isEmpty() || deque.peek() ! ch) { deque.push(ch); } else { deque.pop(); } } String str ; //剩余的元素即为不重复的元素 while (!deque.isEmpty()) { str deque.pop() str; } return str; } }第二种解法双指针法代码逻辑定义快慢指针这里就不用说了快指针负责读慢指针负责写主要的逻辑就是模拟栈的思想而不是实现栈我们可能会想重复的都是两个相同的元素而覆盖操作不是只能覆盖一个元素吗。其实这是对覆盖进行了误解。这就是我们用双指针方法的精髓我们用的是栈的思想但没有 new 任何栈对象。我们把数组本身当成了栈来用组件角色说明fast指针读指针遍历原字符串读取每个字符slow指针写指针/栈顶指针指向栈的下一个空位ch[slow] ch[fast]入栈操作把读到的字符写入栈中ch数组栈的存储空间模拟栈的物理内存ch[slow] ch[fast]; // 这就是入栈操作这里的覆盖操作其实就是入栈操作通过fast指针来读写进slow指针的位置其实就是我们模拟的栈char[] ch s.toCharArray(); // ← 这个数组就是栈 int slow 0; // ← slow 就是栈顶指针java // 查看栈顶元素 if (slow 0 ch[slow] ch[slow - 1]) { // ↑ ↑ // 当前字符 栈顶元素slow-1 // 要入栈 最后一个有效元素 } // 为什么是 slow-1 // 因为有效元素在 [0, slow) 区间 // 区间是左闭右开最后一个有效索引就是 slow-1概念含义位置slow下一个可用位置 / 栈的大小指向空位slow - 1栈顶元素的位置指向最后一个有效元素然后就是我们前面提到的是怎么消除两个元素的如果元素不相等时就相当于是入栈没什么好说的然后就是遇到相同元素的时候如果慢指针的元素和慢指针前一个的元素相等也就是出现了重复元素这里我们进行slow--模拟的就是出栈的操作slow就是栈顶的指针的下一个元素我们把这个slow指针后移了从而栈顶的指针也就移动了slow-1。同时另一个元素也没有入栈因此两个重复元素都没有了。满足了我们的需求。其实这不是真正意义上的移除操作我们只是通过指针来规定边界只看指针范围的内部因此我们是忽视了外界的元素。栈是一种「思想」不一定是「对象」概念说明逻辑上的栈一种数据结构思想后进先出LIFO物理上的栈代码中 new 出来的 Stack、ArrayDeque 对象这道题的关键我们用的是栈的思想但没有 new 任何栈对象。我们把数组本身当成了栈来用题目答案class Solution { public String removeDuplicates(String s) { char[] ch s.toCharArray(); int fast 0; int slow 0; while(fast s.length()){ // 直接用fast指针覆盖slow指针的值 ch[slow] ch[fast]; // 遇到前后相同值的就跳过即slow指针后退一步下次循环就可以直接被覆盖掉了 if(slow 0 ch[slow] ch[slow - 1]){ slow--; }else{ slow; } fast; } return new String(ch,0,slow); } }核心差异对比表对比维度显式栈Deque双指针模拟栈空间复杂度O(n)O(1)是否需要额外容器需要new ArrayDeque()不需要原数组当栈用最终结果处理需要反转栈是倒序直接截取无需反转代码可读性高逻辑清晰中需要理解栈模拟是否修改原数据否是修改原字符数组内存分配堆上分配新对象无额外分配适用场景通用不介意额外空间追求极致性能/空间指标显式栈双指针时间复杂度O(n)O(n)空间复杂度O(n)O(1)内存分配次数2次栈StringBuilder0次只用了原数组CPU缓存友好一般好连续内存访问最后反转需要 O(n)不需要结语如果对你有帮助请点赞关注收藏你的支持就是我最大的鼓励

相关文章:

【LeetCode刷题日记】1047:双栈法与双指针法巧妙消除相邻重复字符

🔥个人主页:北极的代码(欢迎来访) 🎬作者简介:java后端学习者 ❄️个人专栏:苍穹外卖日记,SSM框架深入,JavaWeb ✨命运的结局尽可永在,不屈的挑战却不可须臾或…...

如何彻底解决macOS滚动方向混乱问题:Scroll Reverser完整配置指南

如何彻底解决macOS滚动方向混乱问题:Scroll Reverser完整配置指南 【免费下载链接】Scroll-Reverser Per-device scrolling prefs on macOS. 项目地址: https://gitcode.com/gh_mirrors/sc/Scroll-Reverser 你是否曾经在MacBook触控板和外接鼠标之间切换使用…...

AI代码执行沙箱从POC到生产环境的生死7步(附Gartner评估矩阵与内部审计检查表)

更多请点击: https://intelliparadigm.com 第一章:AI代码执行沙箱从POC到生产环境的生死7步(附Gartner评估矩阵与内部审计检查表) AI代码执行沙箱正从实验室原型快速演进为金融、云原生与DevSecOps流水线中的关键信任组件。然而&…...

终极Blender 3MF插件:从数字设计到3D打印的无缝转换指南

终极Blender 3MF插件:从数字设计到3D打印的无缝转换指南 【免费下载链接】Blender3mfFormat Blender add-on to import/export 3MF files 项目地址: https://gitcode.com/gh_mirrors/bl/Blender3mfFormat 在3D打印工作流中,你是否经常遇到格式转换…...

AI智能体DeepResearchAgent:自动化深度研究助手部署与实战指南

1. 项目概述:一个能帮你“深度思考”的AI研究助手最近在折腾AI应用落地的朋友,估计都听过一个词叫“智能体”(Agent)。这玩意儿说白了,就是让AI不仅能回答问题,还能像人一样,为了完成一个复杂目…...

GSE插件终极指南:如何在魔兽世界中告别复杂宏命令,实现智能一键输出

GSE插件终极指南:如何在魔兽世界中告别复杂宏命令,实现智能一键输出 【免费下载链接】GSE-Advanced-Macro-Compiler GSE is an alternative advanced macro editor and engine for World of Warcraft. 项目地址: https://gitcode.com/gh_mirrors/gs/G…...

LLaMA-Factory数据集格式详解与高质量数据构建方法-方案选型对比

LLaMA-Factory 数据集格式详解与高质量数据构建方法:方案选型对比 1. 问题背景与选型目标 在大模型微调(SFT/DPO/PPO)的工程实践中,“数据决定模型上限”已是共识。然而,许多团队在落地时面临的首要问题并非算法选择&a…...

5分钟快速上手:用Arcade-plus制作你的第一个Arcaea谱面![特殊字符]

5分钟快速上手:用Arcade-plus制作你的第一个Arcaea谱面!🎮 【免费下载链接】Arcade-plus A better utility used to edit and preview aff files 项目地址: https://gitcode.com/gh_mirrors/ar/Arcade-plus 想知道如何轻松制作专业的A…...

LLaMA-Factory数据集格式详解与高质量数据构建方法-原理源码解析

1. 问题背景与分析目标 在大模型训练和应用中,数据集的格式和质量是决定模型性能的关键因素之一。LLaMA-Factory是一个用于企业级AI落地的框架,它简化了大模型的训练、微调和推理过程,特别是在处理企业知识库问答任务时。如何有效地准备和处理…...

告别U盘文件管理烦恼:智能自动备份工具如何让数据同步变得轻松

告别U盘文件管理烦恼:智能自动备份工具如何让数据同步变得轻松 【免费下载链接】USBCopyer 😉 用于在插上U盘后自动按需复制该U盘的文件。”备份&偷U盘文件的神器”(写作USBCopyer,读作USBCopier) 项目地址: htt…...

3步搞定Windows风扇控制:FanControl让你的电脑散热更智能

3步搞定Windows风扇控制:FanControl让你的电脑散热更智能 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub_Trending…...

终极指南:5分钟掌握Locale Remulator系统区域语言模拟器

终极指南:5分钟掌握Locale Remulator系统区域语言模拟器 【免费下载链接】Locale_Remulator System Region and Language Simulator. 项目地址: https://gitcode.com/gh_mirrors/lo/Locale_Remulator Locale Remulator是一款免费高效的系统区域和语言模拟工具…...

线性判别分析(LDA)原理与实战应用指南

1. 线性判别分析的核心价值线性判别分析(Linear Discriminant Analysis, LDA)是我在机器学习项目中最常使用的降维技术之一。与主成分分析(PCA)不同,LDA是一种有监督的线性变换方法,它不仅能降低数据维度&a…...

深入理解W25Q64:基于STM32的SPI Flash存储管理实战(含扇区/块擦除策略)

深入理解W25Q64:基于STM32的SPI Flash存储管理实战 在嵌入式系统开发中,外部Flash存储器扮演着至关重要的角色。W25Q64作为一款8MB容量的SPI NOR Flash芯片,因其高性价比和易用性,成为众多STM32项目的首选存储方案。但真正要发挥它…...

怎样高效解密网易云NCM音乐文件:ncmdumpGUI完全实用指南

怎样高效解密网易云NCM音乐文件:ncmdumpGUI完全实用指南 【免费下载链接】ncmdumpGUI C#版本网易云音乐ncm文件格式转换,Windows图形界面版本 项目地址: https://gitcode.com/gh_mirrors/nc/ncmdumpGUI 你是否曾经为网易云音乐下载的NCM格式文件…...

微信小程序图片裁剪终极指南:如何用we-cropper解决你的图片处理难题

微信小程序图片裁剪终极指南:如何用we-cropper解决你的图片处理难题 【免费下载链接】we-cropper 微信小程序图片裁剪工具 项目地址: https://gitcode.com/gh_mirrors/we/we-cropper 还在为微信小程序中的图片裁剪功能而烦恼吗?你是否遇到过图片显…...

LFM2.5-VL-1.6B前端交互设计:JavaScript实现实时图像上传与结果展示

LFM2.5-VL-1.6B前端交互设计:JavaScript实现实时图像上传与结果展示 1. 引言:当AI视觉遇上Web交互 想象这样一个场景:用户随手拍下一张照片上传到网页,几秒钟后就能获得详细的文字描述和智能问答反馈。这正是LFM2.5-VL-1.6B这类…...

NI-DAQmx计数器频率测量全攻略:从低频到高频,三种方法怎么选不踩坑?

NI-DAQmx计数器频率测量实战指南:方法选型与精度优化策略 在工业自动化、实验室研究和设备监测领域,频率测量是信号分析的基础操作。面对从几赫兹到数兆赫兹的不同信号源,如何选择合适的测量方法并规避常见误差,直接决定了数据的可…...

留一交叉验证(LOOCV)原理与scikit-learn实战指南

1. 理解留一交叉验证(LOOCV)的核心逻辑在机器学习模型评估中,留一交叉验证(Leave-One-Out Cross-Validation, LOOCV)是一种特殊的k折交叉验证形式。当k等于数据集样本数量n时,就形成了LOOCV。这意味着每个样…...

Boot Camp驱动自动化革命:Brigadier如何将45分钟部署压缩至5分钟

Boot Camp驱动自动化革命:Brigadier如何将45分钟部署压缩至5分钟 【免费下载链接】brigadier Fetch and install Boot Camp ESDs with ease. 项目地址: https://gitcode.com/gh_mirrors/bri/brigadier 在企业混合计算环境中,Mac设备Boot Camp驱动…...

多模态传感器自动校准技术解析与应用实践

1. 传感器校准在机器人感知中的核心作用在机器人、自动驾驶车辆和测绘系统中,多模态传感器校准是实现精准环境感知的基础环节。想象一下,当一台自动叉车需要搬运托盘时,它的3D激光雷达负责识别托盘的形状、尺寸和距离,而立体摄像头…...

Visual C++运行库修复工具终极指南:从故障诊断到批量管理

Visual C运行库修复工具终极指南:从故障诊断到批量管理 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否曾经遇到过这样的场景:刚下…...

如何在3分钟内完成音频转文字:AsrTools终极免费解决方案

如何在3分钟内完成音频转文字:AsrTools终极免费解决方案 【免费下载链接】AsrTools ✨ AsrTools: Smart Voice-to-Text Tool | Efficient Batch Processing | User-Friendly Interface | No GPU Required | Supports SRT/TXT Output | Turn your audio into accurat…...

解锁B站缓存视频:m4s-converter如何让你珍藏的内容重获新生

解锁B站缓存视频:m4s-converter如何让你珍藏的内容重获新生 【免费下载链接】m4s-converter 一个跨平台小工具,将bilibili缓存的m4s格式音视频文件合并成mp4 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter 当你在B站发现一个精彩的…...

怎样轻松配置魔兽争霸3优化工具:完整实用指南

怎样轻松配置魔兽争霸3优化工具:完整实用指南 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper 还在为魔兽争霸3在现代电脑上的兼容性问题而…...

RimWorld终极免费模组管理器:3步解决模组冲突,轻松管理200+模组 [特殊字符]

RimWorld终极免费模组管理器:3步解决模组冲突,轻松管理200模组 🎮 【免费下载链接】RimSort RimSort is an open source mod manager for the video game RimWorld. There is support for Linux, Mac, and Windows, built from the ground up…...

终极指南:3步将手机摄像头变身高清视频输入源

终极指南:3步将手机摄像头变身高清视频输入源 【免费下载链接】droidcam-obs-plugin DroidCam OBS Source 项目地址: https://gitcode.com/gh_mirrors/dr/droidcam-obs-plugin 你是否想过用手机摄像头替代昂贵的专业摄像机?DroidCam OBS插件正是你…...

老王-欲望 vs 恐惧:驱动人生的两种原神

欲望 vs 恐惧:驱动人生的两种原神“欲望会吃掉懒惰与矫情, 让人活到命格的天花板。”一、高烧38℃仍在构思选题:是什么在支撑你? 身体虚弱,精神却亢奋半梦半醒间,思维仍在奔涌不是责任感,不是自…...

老王-与辉同行:直播带货进入“人心时代”的里程碑

与辉同行:直播带货进入“人心时代”的里程碑“流量留不住人心,人心自有真情相伴。”一、数据背后的时代转折 首秀战绩(2023年12月9日后一个月): 3小时涨粉300万 → 平均每分钟1.6万人销售额1.5亿元点赞量12.9亿峰值在线…...

如何快速部署多语言语义匹配模型:5个高效优化方案完整指南

如何快速部署多语言语义匹配模型:5个高效优化方案完整指南 【免费下载链接】paraphrase-multilingual-MiniLM-L12-v2 项目地址: https://ai.gitcode.com/hf_mirrors/ai-gitcode/paraphrase-multilingual-MiniLM-L12-v2 paraphrase-multilingual-MiniLM-L12-…...