20. 有效的括号
括号匹配是栈解决的基本问题,本题的基本思路是考虑不匹配的情况:
- 字符串里左方向的括号多余了
- 括号没有多余,但是 括号的类型没有匹配上。
- 字符串里右方向的括号多余了
遍历字符串,如果遇到的是左括号,则将与之匹配的右括号入栈,如果是右括号,则和栈顶元素匹配,如果不相同说明是第二种不匹配的情况,如果相同则将此栈顶元素出栈;如果最后字符串遍历完了但是栈还不为空,说明是第一种不匹配的情况;如果字符串还没有遍历完但是栈为空了,说明是第二种不匹配的情况
注意:
此题可以增加一种剪枝,如果字符串长度为奇数,则一定不匹配
class Solution {
public:
bool isValid(string s) {
stack<char> st;
//剪枝
if (s.size() % 2 != 0) return false;
for (int i = 0; i < s.size(); i++) {
//左括号则将匹配的右括号入栈
if (s[i] == '(')st.push(')');
if (s[i] == '[')st.push(']');
if (s[i] == '{')st.push('}');
//右括号则匹配栈
if (s[i] == ')' || s[i] == ']' || s[i] == '}') {
//栈为空 第三种不匹配情况
//不等于栈顶元素 第二种不匹配情况
if(st.empty()||s[i]!=st.top())return false;
//栈不为空出栈
if (st.empty() != true) {
st.pop();
}
}
}
//栈不空则第一种不匹配 空了则匹配
return st.empty();
}
};
问题:s[i]!=st.top()此处需要先考虑栈是否为空,如果是空的话执行此处会出现异常
1047. 删除字符串中的所有相邻重复项
本题比较简单,也是栈的一个应用,遍历字符串,如果该字符和栈顶元素不相同或者当前栈是空的则入栈,如果相同则将栈顶元素出栈,最后留在栈里面的就是倒序的答案,将其反转就得到了真正的答案
class Solution {
public:
string removeDuplicates(string s) {
string result;
stack<char> a;
for (int i = 0; i < s.size(); i++) {
if (a.empty() || s[i] != a.top())a.push(s[i]);
//s[i]=a.top()
else a.pop();
}
while (!a.empty()) {
result += a.top();
a.pop();
}
reverse(result.begin(), result.end());
return result;
}
};
注意:
将栈顶元素放到字符串中使用result += a.top();
将字符串反转时使用reverse(result.begin(), result.end());
150. 逆波兰表达式求值
本题也是使用栈完成,当遇到数字的时候入栈,遇到运算符的时候将栈顶的两个元素(注意顺序,先取出的元素应该在后面,后取出的元素应该在前面,否则减法和除法会发生问题)取出做运算,直至结束
注意:
本题需要把字符串转换成longlong类型的数字,用的函数是stoll,同理,转换为int 型的函数为stoi,转换成long型的为stol
class Solution {
public:
int evalRPN(vector<string>& tokens) {
int result=0;
stack<long long> s;
for (int i = 0; i < tokens.size(); i++) {
//符号则出栈
if (tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/") {
int y = s.top();
s.pop();
int x = s.top();
s.pop();
if (tokens[i] == "+")result = x + y;
if (tokens[i] == "-")result = x - y;
if (tokens[i] == "*")result = x * y;
if (tokens[i] == "/")result = x / y;
s.push(result);
}
//数字则入栈
else {
s.push(stoll(tokens[i]));
}
}
result = s.top();
return result;
}
};