算法分析 —— 《栈》

server/2025/3/3 14:59:55/

文章目录

  • 删除字符串中的所有相邻重复项
    • 题目描述:
    • 代码实现:
    • 代码解析:
  • 比较含退格的字符串
    • 题目描述:
    • 代码实现:
    • 代码解析:
  • [基本计算器 II](https://leetcode.cn/problems/remove-all-adjacent-duplicates-in-string/)
    • 题目描述:
    • 代码实现:
    • 代码解析:
  • 字符串解码
    • 题目描述:
    • 代码实现:
    • 代码解析:
  • 验证序列
    • 题目描述:
    • 代码实现:
    • 代码解析:

删除字符串中的所有相邻重复项

题目描述:

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

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

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

示例:

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

代码实现:

class Solution 
{
public:string removeDuplicates(string s) {string st;for(auto& x : s){if(st.size() && st.back() == x) st.pop_back();else st.push_back(x);}return st;}
};

代码解析:

这道题就是一道消消乐,当两个相邻一样得字符一样,那就直接消除掉,所以我们可以结合之前刷过的题来看,我们可以运用“”这个数据结构,来帮助我们完成消消乐。

但是这个数据结构还是太大了,所以对于都是小写字母得这道题来说,我们直接使用字符串来模拟就好了。

所以我们直接遍历整个字符串,如果该元素与顶元素一致,那就直接删掉顶元素。

否则直接加进到里即可。

比较含退格的字符串

题目描述:

给定 st 两个字符串,当它们分别被输入到空白的文本编辑器后,如果两者相等,返回 true# 代表退格字符。

**注意:**如果对空文本输入退格字符,文本继续为空。

示例 1:

输入:s = "ab#c", t = "ad#c"
输出:true
解释:s 和 t 都会变成 "ac"。

示例 2:

输入:s = "ab##", t = "c#d#"
输出:true
解释:s 和 t 都会变成 ""。

示例 3:

输入:s = "a#c", t = "b"
输出:false
解释:s 会变成 "c",但 t 仍然是 "b"。

代码实现:

class Solution 
{
public:bool backspaceCompare(string s, string t) {string st1, st2;for(auto& ch : s){if(st1.size() && ch == '#') st1.pop_back();else if(ch != '#') st1 += ch;}for(auto& ch : t){if(st2.size() && ch == '#') st2.pop_back();else if(ch != '#') st2 += ch;}return st1 == st2;}
};

代码解析:

题目意思和上面那道题差不多, 本质还是个小的消消乐,在这里我就不过多赘述了。

基本计算器 II

题目描述:

给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。

整数除法仅保留整数部分。

你可以假设给定的表达式总是有效的。所有中间结果将在 [-231, 231 - 1] 的范围内。

**注意:**不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval()

示例 1:

输入:s = "3+2*2"
输出:7

示例 2:

输入:s = " 3/2 "
输出:1

示例 3:

输入:s = " 3+5 / 2 "
输出:5

代码实现:

class Solution 
{
public:int calculate(string s) {vector<int> st;char op = '+';for(int i = 0; i < s.size(); ){if(s[i] == ' ') ++i;else if(s[i] >= '0' && s[i] <= '9'){int tmp = 0;while(i < s.size() && s[i] >= '0' && s[i] <= '9')tmp = tmp * 10 + (s[i++] - '0');if(op == '+') st.push_back(tmp);else if(op == '-') st.push_back(-tmp);else if(op == '*') st.back() *= tmp;else if(op == '/') st.back() /= tmp;}else{op = s[i];++i;}}int ans = 0;for(auto& x : st) ans += x;return ans;}
};

代码解析:

题目描述是让我们实现一个计算器,只是一个小型得计算器因为只涉及加减乘除。

那么针对这道题来说,我得建议是将所有数字丢到里面,
1、如果数字前面得运算符是‘+’那就直接丢到里面。
2、如果数字前面的运算符是‘-’那就取相反数丢到里面。
3、如果数字前面的运算符是‘*’那就将顶元素乘等当前数字。
4、如果数字前面的运算符是‘/’那就将顶元素除等当前数字。

还要一种细节问题,我们的数字在字符串中会有连续的数字,那么这种情况我们也要考虑进去。

具体的做法就是,不断的往该数字后面走,走一次乘等10再加上自己,直到走到了一个运算符或者越界之后即可。

同理,在我们查找到元素为数字之后,我们最后的 i 就会在内部被我们移动到运算符上或者越界。

字符串解码

题目描述:

给定一个经过编码的字符串,返回它解码后的字符串。

编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。

你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。

此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a2[4] 的输入。

示例 1:

输入:s = "3[a]2[bc]"
输出:"aaabcbc"

示例 2:

输入:s = "3[a2[c]]"
输出:"accaccacc"

示例 3:

输入:s = "2[abc]3[cd]ef"
输出:"abcabccdcdcdef"

示例 4:

输入:s = "abc3[cd]xyz"
输出:"abccdcdcdxyz"

代码实现:

class Solution 
{
public:string decodeString(string s) {stack<string> st_s;stack<int> st_i;st_s.push("");for(int i = 0; i < s.size();){if(s[i] >= '0' && s[i] <= '9'){int tmp = 0;while(i < s.size() && s[i] >= '0' && s[i] <= '9')tmp = tmp * 10 + (s[i++] - '0');st_i.push(tmp);    }else if(s[i] == '['){++i;string tmp = ""; // 一定要在这里创建空数组!while(i < s.size() && s[i] >= 'a' && s[i] <= 'z')tmp += s[i++];st_s.push(tmp);}else if(s[i] == ']'){string tmp = st_s.top();int k = st_i.top();st_i.pop();st_s.pop();while(k--)st_s.top() += tmp;++i;}else if(s[i] >= 'a' && s[i] <= 'z'){st_s.top() += s[i++];}}return st_s.top();}
};

代码解析:

题目描述也是非常的简单啊,但是这个代码有点不好写,其实本质这些的题目都是围绕着模拟来展开的。现在就是你给我个2[ac],我就要给你变成acac。这就是题目的基本意思,但是会有一种情况,题目会给你这样的例子:2[ab2[2[cc]]最后转换就是abccccccccabcccccccc,所以他是会出嵌套的情况,而针对数字,也会有两位数以上的数字,那这里我们还要进行处理。

1、如果遍历到数字,按上题的方式找到两位数及以上入st_i
2、如果遍历到字母,按上题的方式找到一个整个字符串,加在st_s顶元素字符串后。
3、如果遍历到’[‘,先++i,最重要的是要先创建一个空字符串tmp,然后凭借记录在tmp里,最后将后面的字符串找到,丢到st_s里。
4、如果遍历到’]',取出st_i顶元素,和st_s顶元素,分别以k和tmp记录下来,然后丢掉st_s顶元素,之后循环k次,给新的st_s顶元素 += tmp。

验证序列

题目描述:

给定 pushedpopped 两个序列,每个序列中的 值都不重复,只有当它们可能是在最初空上进行的推入 push 和弹出 pop 操作序列的结果时,返回 true;否则,返回 false

示例 1:

输入:pushed = [1,2,3,4,5], popped = [4,5,3,2,1]
输出:true
解释:我们可以按以下顺序执行:
push(1), push(2), push(3), push(4), pop() -> 4,
push(5), pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1

示例 2:

输入:pushed = [1,2,3,4,5], popped = [4,3,5,1,2]
输出:false
解释:1 不能在 2 之前弹出。

代码实现:

class Solution 
{
public:bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {stack<int> st;int i = 0;for(auto& x : pushed){st.push(x);while(st.size() && popped[i] == st.top()){st.pop();++i;}}return i == popped.size();}
};

代码解析:

题目描述我们也好理解,如果有尝试考研的同学肯定有做过这道题,简单来说,拿示例1来看,我们有一个,我可以先push1 2 3 4,然后把4给推出去,这样剩下就只有1 2 3,接下来想要推5出去,但我没有,所以我就加到5,加到了然后推出去。后面仍然是1 2 3,然后想要推出去的就是3 2 1,所以最终就是空的了。


http://www.ppmy.cn/server/172098.html

相关文章

Linux 第三次脚本作业

源码编译安装httpd 2.4&#xff0c;提供系统服务管理脚本并测试&#xff08;建议两种方法实现&#xff09; 一、第一种方法 1、把 httpd-2.4.63.tar.gz 这个安装包上传到你的试验机上 2、 安装编译工具 (俺之前已经装好了&#xff09; 3、解压httpd包 4、解压后的httpd包的文…

图像伽马矫正 + 亮度调整 + 对比度调整

伽马校正 人眼对亮度的感知是非线性的&#xff0c;对暗部变化更敏感&#xff0c;而相机和显示器的响应通常是线性的。因此&#xff0c;直接显示线性数据会导致图像看起来不自然。伽马校正通过非线性变换解决这一问题。 数学公式&#xff1a; E ′ E γ 其中&#xff1a; E …

Node.js安装与学习的简单记录

1. 下载与安装 参考&#xff1a; 2024最新版Node.js下载安装及环境配置教程【保姆级】 Node.js中文网 选择长期维护版: 18.19.0&#xff0c;Windows 安装包 (.msi) 64位。 安装选项都默认&#xff0c;安装路径可以改一下。 查看node版本&#xff1a;node -v v18.19.0 查看npm版…

微服务学习(5):消息转换器由JDK序列化——JSON序列化

在企业应用中&#xff0c;将消息转换器从JDK序列化改为JSON序列化提升了系统间通信的效率与安全性。JSON作为轻量级数据交换格式&#xff0c;增强了跨平台兼容性&#xff0c;简化了开发与维护。相比JDK序列化&#xff0c;JSON序列化减少了潜在的安全风险&#xff0c;提供了更紧…

强化学习策略梯度算法实现文档(CartPole-v1)

1. 概述 本代码使用策略梯度方法&#xff08;Policy Gradient&#xff09;解决OpenAI Gym的CartPole-v1环境问题&#xff0c;包含以下核心组件&#xff1a; 策略网络&#xff1a;神经网络输出动作概率分布 REINFORCE算法&#xff1a;带熵正则化的策略梯度方法 训练监控&…

Spring Boot 与 MyBatis 数据库操作

一、核心原理 Spring Boot 的自动配置 通过 mybatis-spring-boot-starter 自动配置 DataSource&#xff08;连接池&#xff09;、SqlSessionFactory 和 SqlSessionTemplate。 扫描 Mapper 接口或指定包路径&#xff0c;生成动态代理实现类。 MyBatis 的核心组件 SqlSessionF…

【实战 ES】实战 Elasticsearch:快速上手与深度实践-2.1.1动态映射(Dynamic Mapping)的合理控制

&#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 文章大纲 Elasticsearch动态映射的合理控制与最佳实践1. 动态映射核心原理1.1 动态映射工作机制1.2 核心处理流程 2. 动态映射配置策略2.1 动态模式对照表2.2 配置示例 3. 字段类型自…

java容器 LIst、set、Map

Java容器中的List、Set、Map是核心数据结构&#xff0c;各自适用于不同的场景 一、List&#xff08;有序、可重复&#xff09; List接口代表有序集合&#xff0c;允许元素重复和通过索引访问&#xff0c;主要实现类包括&#xff1a; ArrayList 底层结构&#xff1a;动态数组…