目录
栈的应用场景:
1、 1047. 删除字符串中的所有相邻重复项
2、844. 比较含退格的字符串
3、 227. 基本计算器 II
4、394. 字符串解码
5、946. 验证栈序列
栈的应用场景:
-
表达式求值:栈常用于中缀表达式转换为后缀表达式,或者用于计算后缀表达式的值。栈可以帮助处理运算符的优先级和结合性。
-
括号匹配:栈可以用来检查表达式中的括号是否匹配。遍历表达式,遇到左括号时将其入栈,遇到右括号时与栈顶元素匹配,如果匹配则出栈,否则括号不匹配。
-
深度优先搜索(DFS):在树或图的深度优先搜索中,栈通常用于存储待访问的节点。每次访问一个节点时,将其邻居节点入栈,以便后续继续深度遍历。
-
逆波兰表达式:栈可以用于计算逆波兰表达式(后缀表达式)。遍历表达式,遇到操作数则入栈,遇到操作符则从栈中弹出操作数进行计算。
-
函数调用:在编程语言中,函数调用的实现通常使用栈。每次调用函数时,将函数参数、返回地址等信息压入栈中,函数返回时再从栈中弹出这些信息。
-
迷宫求解:栈可以用于迷宫求解算法中,记录走过的路径。在搜索迷宫的过程中,将当前位置入栈,如果遇到死路则回溯到上一个位置。
这些是栈在算法中常见的应用场景,栈的特性使其在处理递归、回溯、以及需要后进先出(LIFO)顺序的问题时非常有用。
1、 1047. 删除字符串中的所有相邻重复项
思路:符合后进先出,⽤数组模拟栈。
class Solution {
public:string removeDuplicates(string s) {string ret;for (auto ch : s) {if (ret.size() && ret.back() == ch) {ret.pop_back();} else {ret += ch;}}return ret;}
};
2、844. 比较含退格的字符串
思路:符合后进先出,⽤数组模拟栈。
class Solution {
public:bool backspaceCompare(string s, string t) { return judge(s) == judge(t); }string judge(string& s) {string ret;for (auto ch : s) {if (ch == '#') {if (ret.size())ret.pop_back();} else {ret += ch;}}return ret;}
};
3、 227. 基本计算器 II
思路:分类讨论,模拟实现
- 遇到操作符: 更新操作符char op
- 遇到数字:
- 先把数字提取出来, tmp;
- 分情况讨论,根据 op 的符号
- op == ‘+’ tmp 直接入栈:
- op == ‘-’ tmp 入栈
- op == ‘*’ 直接乘到栈顶元素上:
- op == ‘/’ 直接除到栈顶元素上
class Solution {
public:int calculate(string s) {int n = s.size();vector<int> st;char op = '+';int i = 0;while (i < n) {if (s[i] == ' ')i++;else if (s[i] >= '0' && s[i] <= '9') {int tmp = 0;while (i < n && 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;elsest.back() /= tmp;} elseop = s[i++];}int sum = 0;for (auto n : st)sum += n;return sum;}
};
4、394. 字符串解码
思路:这段代码是一个用于解码经过编码的字符串的函数。它使用了两个栈来处理解码过程,一个用于存储字符串,另一个用于存储重复次数。
在代码中,首先初始化了一个空字符串栈
st
,并将一个空字符串压入栈中。然后初始化一个空的整数栈nums
。接着使用一个循环来遍历输入字符串s
。
- 如果当前字符是数字,则将连续的数字字符转换为一个整数,并将其压入整数栈
nums
。- 如果当前字符是左括号
[,
则将空字符串压入字符串栈st
,并继续向后提取括号内的字符串。- 如果当前字符是右括号
]
,则将栈顶字符串弹出,同时弹出对应的重复次数,然后将该字符串重复相应次数并添加到上一个字符串中。- 如果当前字符是字母,则将连续的字母字符添加到栈顶字符串中。
最终,函数返回栈顶的字符串,即解码后的结果。
class Solution {
public:string decodeString(string s) {stack<string> st;stack<int> nums;st.push("");int i = 0, n = s.size();while (i < n) {if (s[i] >= '0' && s[i] <= '9') {int tmp = 0;while (s[i] >= '0' && s[i] <= '9') {tmp = tmp * 10 + (s[i++] - '0');}nums.push(tmp);} else if (s[i] == '[') {string tmp = "";i++;// 把括号后⾯的字符串提取出来while (s[i] <= 'z' && s[i] >= 'a') {tmp += s[i++];}st.push(tmp);} else if (s[i] == ']') {string tmp = st.top();st.pop();int n = nums.top();nums.pop();while (n--) {st.top() += tmp;}i++;} else {while (i < n && s[i] >= 'a' && s[i] <= 'z') {st.top() += s[i++];}}}return st.top();}
};
5、946. 验证栈序列
思路:⽤栈来模拟进出栈的流程。 ⼀直让元素进栈,进栈的同时判断是否需要出栈,同时记录出栈的元素个数。当所有元素模拟完毕之后,判断如果出栈元素个数等于popped数组,则验证成功,反之验证失败。
class Solution {
public:bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {stack<int> st;int i=0,n=popped.size();for(auto x:pushed){st.push(x);while(st.size()&&st.top()==popped[i]){st.pop();i++;}} return i==n;}
};