前端算法 ==== 栈的好戏还要继续!| 1047. 删除字符串中的所有相邻重复项

目录

解题

思路

题外话


给出由小写字母组成的字符串 S重复项删除操作会选择两个相邻且相同的字母,并删除它们。

在 S 上反复执行重复项删除操作,直到无法继续删除。

在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

复制代码
输入:"abbaca"
输出:"ca"
解释:
例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。

解题

充分理解题意后,我们可以发现,当字符串中同时有多组相邻重复项时,我们无论是先删除哪一个,都不会影响最终的结果。因此我们可以从左向右顺次处理该字符串。

而消除一对相邻重复项可能会导致新的相邻重复项出现,如从字符串 abba 中删除 bb 会导致出现新的相邻重复项 aa 出现。因此我们需要保存当前还未被删除的字符。一种显而易见的数据结构呼之欲出:栈。我们只需要遍历该字符串,如果当前字符和栈顶字符相同,我们就贪心地将其消去,否则就将其入栈即可。

思路

本题要删除相邻相同元素,相对于20. 有效的括号来说其实也是匹配问题,20. 有效的括号 是匹配左右括号,本题是匹配相邻元素,最后都是做消除的操作。

本题也是用栈来解决的经典题目。

那么栈里应该放的是什么元素呢?

我们在删除相邻重复项的时候,其实就是要知道当前遍历的这个元素,我们在前一位是不是遍历过一样数值的元素,那么如何记录前面遍历过的元素呢?

所以就是用栈来存放,那么栈的目的,就是存放遍历过的元素,当遍历当前的这个元素的时候,去栈里看一下我们是不是遍历过相同数值的相邻元素。

然后再去做对应的消除操作。 如动画所示:

从栈中弹出剩余元素,此时是字符串ac,

/**
 * 移除字符串中相邻字符对的函数
 * 该函数通过模拟栈操作,依次遍历字符串中的字符,每当遇到不匹配的相邻字符时,将其重新压入栈中
 * 最终,栈中剩余的字符即为去除所有相邻字符对后的结果
 *
 * @param {string} s 输入的字符串
 * @return {string} 移除相邻字符对后的字符串
 */
var removeDuplicates = function (s) {
  // 使用数组模拟栈数据结构
  const stack = [];
  // 遍历输入字符串的每个字符
  for (const x of s) {
    // 弹出栈顶元素,用于比较是否与当前字符x相同
    let prev = stack.pop();
    // 如果弹出的元素与当前字符x不同,则将弹出的元素重新压入栈,并将当前字符x也压入栈
    if (prev !== x) {
      stack.push(prev);
      stack.push(x);
    }
    // 如果相同,则不做任何操作,即实现了移除一对相邻字符的目的
  }
  // 最终栈中剩余的字符即为结果,将其转换为字符串返回
  return stack.join("");
};

// 调用示例
removeDuplicates("abbaca");

题外话

这道题目就像是我们玩过的游戏对对碰,如果相同的元素放在挨在一起就要消除。

可能我们在玩游戏的时候感觉理所当然应该消除,但程序又怎么知道该如果消除呢,特别是消除之后又有新的元素可能挨在一起。

此时游戏的后端逻辑就可以用一个栈来实现(我没有实际考察对对碰或者爱消除游戏的代码实现,仅从原理上进行推断)。

游戏开发可能使用栈结构,编程语言的一些功能实现也会使用栈结构,实现函数递归调用就需要栈,但不是每种编程语言都支持递归,例如:

递归的实现就是:每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中,然后递归返回的时候,从栈顶弹出上一次递归的各项参数,所以这就是递归为什么可以返回上一层位置的原因。

相信大家应该遇到过一种错误就是栈溢出,系统输出的异常是Segmentation fault(当然不是所有的Segmentation fault 都是栈溢出导致的) ,如果你使用了递归,就要想一想是不是无限递归了,那么系统调用栈就会溢出。

而且在企业项目开发中,尽量不要使用递归!在项目比较大的时候,由于参数多,全局变量等等,使用递归很容易判断不充分return的条件,非常容易无限递归(或者递归层级过深),造成栈溢出错误(这种问题还不好排查!)

相关推荐
轻口味12 分钟前
【每日学点鸿蒙知识】AVCodec、SmartPerf工具、web组件加载、监听键盘的显示隐藏、Asset Store Kit
前端·华为·harmonyos
alikami15 分钟前
【若依】用 post 请求传 json 格式的数据下载文件
前端·javascript·json
古希腊掌管学习的神26 分钟前
[LeetCode-Python版]相向双指针——611. 有效三角形的个数
开发语言·python·leetcode
赵钰老师27 分钟前
【R语言遥感技术】“R+遥感”的水环境综合评价方法
开发语言·数据分析·r语言
V+zmm1013433 分钟前
基于微信小程序的乡村政务服务系统springboot+论文源码调试讲解
java·微信小程序·小程序·毕业设计·ssm
就爱学编程35 分钟前
重生之我在异世界学编程之C语言小项目:通讯录
c语言·开发语言·数据结构·算法
吃杠碰小鸡1 小时前
lodash常用函数
前端·javascript
Oneforlove_twoforjob1 小时前
【Java基础面试题025】什么是Java的Integer缓存池?
java·开发语言·缓存
emoji1111111 小时前
前端对页面数据进行缓存
开发语言·前端·javascript
xmh-sxh-13141 小时前
常用的缓存技术都有哪些
java