20. 有效的括号
文章:代码随想录 (programmercarl.com)
视频:栈的拿手好戏!| LeetCode:20. 有效的括号_哔哩哔哩_bilibili
思路:
先来分析一下 这里有三种不匹配的情况,
- 第一种情况,字符串里左方向的括号多余了 ,所以不匹配。
- 第二种情况,括号没有多余,但是 括号的类型没有匹配上。
- 第三种情况,字符串里右方向的括号多余了,所以不匹配。
我们的代码只要覆盖了这三种不匹配的情况,就不会出问题,可以看出 动手之前分析好题目的重要性。
第一种情况:已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false
第二种情况:遍历字符串匹配的过程中,发现栈里没有要匹配的字符。所以return false
第三种情况:遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号return false
那么什么时候说明左括号和右括号全都匹配了呢,就是字符串遍历完之后,栈是空的,就说明全都匹配了。
class Solution {
public:
bool isValid(string s) {
/*
1. 左括号多余:([{}]()
2. 左右括号不匹配:[{(}}]
3. 右括号多余:[{}]())))
*/
stack<char> st;
//如果字符串长度为奇数,直接返回false
if (s.size() % 2 != 0)
{
return false;
}
for (int i = 0; i < s.size(); i++)
{
//如果遍历到的元素是左括号,则向栈中压入对应的右括号
if (s[i] == '{')
{
st.push('}');
}
else if (s[i] == '[') {
st.push(']');
}
else if (s[i] == '(') {
st.push(')');
}
/*
如果遍历到的元素是右括号
① 遍历过程中栈为空 —> 3
② 当前遍历到的元素与栈顶元素不匹配 —> 2
*/
else if (st.empty() || s[i] != st.top()) {
return false;
}
else {
st.pop();
}
}
//如果栈为空,则所有符号都匹配成功
//如果栈非空,则为情况一,左括号多余
return st.empty();
}
};
1047. 删除字符串中的所有相邻重复项
文章:代码随想录 (programmercarl.com)
视频:栈的好戏还要继续!| LeetCode:1047. 删除字符串中的所有相邻重复项_哔哩哔哩_bilibili
思路:
那么栈里应该放的是什么元素呢?
我们在删除相邻重复项的时候,其实就是要知道当前遍历的这个元素,我们在前一位是不是遍历过一样数值的元素,那么如何记录前面遍历过的元素呢?
所以就是用栈来存放,那么栈的目的,就是存放遍历过的元素,当遍历当前的这个元素的时候,去栈里看一下我们是不是遍历过相同数值的相邻元素。
然后再去做对应的消除操作。 如动画所示:
可以拿字符串直接作为栈,这样省去了栈还要转为字符串的操作。
//push_back():向数组或字符串的尾部添加元素
//pop_back():弹出数组或字符串尾部元素
//push_front():向数组或字符串的头部添加元素
//pop_front():弹出数组或字符串头部元素
class Solution {
public:
string removeDuplicates(string s) {
//使用字符串模拟栈,字符串的头部为栈底,字符串尾部为栈顶
string result;
for (char c : s)
{
//如果结果集(栈)为空,或当前遍历元素与栈顶元素(字符串中当前字符前一位,result的串尾元素)不相等,将当前元素加到栈顶(result字符串尾部)
if (result.empty() || c != result.back())
{
result.push_back(c);
}
//如果当前元素与栈顶元素相等,则弹出栈顶元素(字符串尾部元素)
else {
result.pop_back();
}
}
return result;
}
};
150. 逆波兰表达式求值
文章:代码随想录 (programmercarl.com)
视频:栈的最后表演! | LeetCode:150. 逆波兰表达式求值_哔哩哔哩_bilibili
思路:
那么来看一下本题,其实逆波兰表达式相当于是二叉树中的后序遍历。 大家可以把运算符作为中间节点,按照后序遍历的规则画出一个二叉树。
但我们没有必要从二叉树的角度去解决这个问题,只要知道逆波兰表达式是用后序遍历的方式把二叉树序列化了,就可以了。
在进一步看,本题中每一个子表达式要得出一个结果,然后拿这个结果再进行运算,那么这岂不就是一个相邻字符串消除的过程,和1047.删除字符串中的所有相邻重复项 (opens new window)中的对对碰游戏是不是就非常像了。
*
/ \
+ +
/ \ / \
1 2 3 4
class Solution {
public:
int evalRPN(vector<string>& tokens) {
stack<long long> st;
for (int i = 0; i < tokens.size(); i++)
{
//当前遍历的元素为+-*/,在栈中取出两个元素,利用该符号进行运算,将运算结果压入栈中
if (tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/")
{
long long num1 = st.top();
st.pop();
long long num2 = st.top();
st.pop();
if (tokens[i] == "+") {
st.push(num2 + num1);
}
if (tokens[i] == "-") {
st.push(num2 - num1);
}
if (tokens[i] == "*") {
st.push(num2 * num1);
}
if (tokens[i] == "/") {
st.push(num2 / num1);
}
}
else {
//如果当前遍历元素为数字,将当前元素直接压入栈中
st.push(stoll(tokens[i]));
}
}
int result = st.top();
st.pop();
return result;
}
};
标签:11,遍历,括号,元素,随想录,st,tokens,字符串,求值
From: https://www.cnblogs.com/chaoyue-400/p/17035827.html