20. 有效的括号
要点
- 不匹配的三种情况:左括号多了、右括号多了、对应括号不匹配
- 对每次遍历到某个字符,可进行的操作:
-
- 是左括号,入栈
-
- 右括号,看是否匹配
-
- 栈已空,缺少左括号
-
- 字符串遍历结束,栈非空,左括号多了
括号匹配
class Solution {
public:
bool isValid(string s) {
stack<char> st;
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(']');
//两种返回false的情况如下
else if (st.empty() || s[i] != st.top()) return false;
else st.pop();
}
//第三种返回false的情况
return st.empty();
}
};
总结
if的条件撇去入栈的操作就剩下返回false的操作和匹配时pop的操作,在遍历过程中,两种false的情况可以直接return,还有一种得遍历完才发现。
优化:最开始判断s.size()是否为奇数,若是就直接return.
1047. 删除字符串中的所有相邻重复项
要点
string不支持push_front,emplace_front,只能从串尾追加字符或字符串- 头文件 “algorithm”的函数
reverse(),参数为两个迭代器,翻转容器内的元素 stack,queue容器都不能用迭代器遍历
消消乐
class Solution {
public:
string removeDuplicates(string s) {
stack<char> st;
for (char c : s) {
if (st.empty() || c != st.top()) {
st.push(c);
}else {
st.pop();
}
}
string res = "";
while (!st.empty()) {
res += st.top();
st.pop();
}
reverse(res.begin(), res.end());
return res;
}
};
总结
用stack作消消乐,再将其中的元素转为string。也可以直接在string上作消消乐操作push_back, pop_back
150. 逆波兰表达式求值
要点
- 逆波兰式相当于是二叉树的后序遍历,其中运算符为中间节点,数字为子节点。最先进行的运算在叶子节点
- 本题的所有数字和中间结果都是32位整数内,不管是32位还是64位编译器,
long都够用了 - 在类中,如果什么都没有,则类占用1个字节;只有成员函数也是只占1字节
stol,stoll函数,字符串转long,long long
求值
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(num1 + num2);
if (tokens[i] == "-") st.push(num2 - num1); //出bug
if (tokens[i] == "*") st.push(num1 * num2);
if (tokens[i] == "/") st.push(num2 / num1); //出bug
}else {
st.push(stoll(tokens[i]));
}
}
return st.top();
}
};
总结
注意:st.top()出的num的运算顺序!