目录
三道题都使用栈来解决,不难。
20. 有效的括号
题目链接:20. 有效的括号
给定一个只包括
'('
,')'
,'{'
,'}'
,'['
,']'
的字符串s
,判断字符串是否有效。有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
示例 1:
输入:s = "()" 输出:true示例 2:
输入:s = "()[]{}" 输出:true示例 3:
输入:s = "(]" 输出:false
-
思考过程:
- 使用栈(先进后出)来做匹配类题目
- 遍历字符串,遇到左括号则在栈内存储右括号,遇到右括号则判断当前和栈顶元素是否匹配
- 有三种不匹配的情况:左括号多余(遍历完字符串,栈为不空);不匹配;右括号多余(遍历到右括号时栈为空,没有多余的元素)
-
力扣代码:
class Solution {
public:
bool isValid(string s) {
if(s.size() % 2 == 1) return false; // 如果为奇数一定为 false
std::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('}');
// else if (s[i] != st.top() || st.empty()) return false; // 第二、三种情况
else if (st.empty() || s[i] != st.top()) return false; // 第二、三种情况
else st.pop(); // 此时栈已不为空
}
return st.empty(); // 第一种情况
}
};
// 一般在使用st.pop() st.top() 时要判断栈是否为空,避免发生未定义的行为。
// 因此在本程序中,else if (st.empty() || s[i] != st.top()) 中的 st.empty() 判断才要放到前面;
1047. 删除字符串中的所有相邻重复项
题目链接:1047. 删除字符串中的所有相邻重复项
给出由小写字母组成的字符串
S
,重复项删除操作会选择两个相邻且相同的字母,并删除它们。在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
示例:
输入:"abbaca" 输出:"ca" 解释: 例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。
-
思考过程:
通过栈的“ 后进先出 ”原则,判断当前元素和栈顶元素是否相同,如果相同则移除栈顶元素
-
力扣代码:
class Solution {
public:
string removeDuplicates(string s) {
std::stack<char> st;
for (int i = 0; i < s.size(); i++) {
if (st.empty()){
st.push(s[i]);
} else {
if (s[i] == st.top()) st.pop();
else st.push(s[i]);
}
}
// 将栈中的元素放到result返回
string result = "";
while (!st.empty()) {
result +=st.top();
st.pop();
}
reverse (result.begin(), result.end()); // 字符串反转
return result;
}
};
150. 逆波兰表达式求值
题目链接:150. 逆波兰表达式求值
给你一个字符串数组
tokens
,表示一个根据 逆波兰表示法 表示的算术表达式。请你计算该表达式。返回一个表示表达式值的整数。
示例 1:
输入:tokens = ["2","1","+","3","*"] 输出:9 解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9
逆波兰表达式:
逆波兰表达式是一种后缀表达式,所谓后缀就是指算符写在后面。
- 平常使用的算式则是一种中缀表达式,如
( 1 + 2 ) * ( 3 + 4 )
。- 该算式的逆波兰表达式写法为
( ( 1 2 + ) ( 3 4 + ) * )
。逆波兰表达式主要有以下两个优点:
- 去掉括号后表达式无歧义,上式即便写成
1 2 + 3 4 + *
也可以依据次序计算出正确结果。- 适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中。
-
力扣代码:
// 计算机中后缀表达式的计算
class Solution {
public:
int evalRPN(vector<string>& tokens) {
std::stack<int> st;
for (int i = 0; i < tokens.size(); i++) {
if (tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/") {
int num1 = st.top();
st.pop();
int 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(stoi(tokens[i])); // 将表示整数的字符 转换成 整数
}
}
int result = st.top();
st.pop(); // 把栈里最后一个元素弹出(不弹出也没事)
return result;
}
};