LeetCode20 有效的括号
题目链接:有效的括号
思路
括号匹配是栈的经典应用,408中也比较常见:遍历字符串s,遇到三种左括号入栈,遇到右括号则比对,若栈为空(右括号数量多于左括号)或栈顶不是同一类型的左括号则return false;若是同一类型的左括号则匹配成功将栈顶元素弹出,继续遍历。遍历结束后若栈为空,则说明所有括号均匹配,return true,否则说明左括号多于右括号,return false。
注:①遇到左括号时可以将对应的右括号入栈,这样后面遍历到右括号时更易进行判断;②当字符串为奇数时括号一定不匹配,适当剪枝。
代码
class Solution {
public:
bool isValid(string s) {
if (s.size() % 2 != 0)
return false; // 如果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(']');
else if (st.empty() || st.top() != s[i])
return false;
else
st.pop(); // st.top() 与 s[i]相等,栈弹出元素
}
return st.empty();
}
};
复杂度
时间复杂度:O(n)
空间复杂度:O(n)
Leetcode1047 重复的子字符串
题目链接:重复的子字符串
思路
与上题类似,本题使用栈将重复的元素消去,遍历后栈中剩下的元素即为结果的倒序,再逆置一次即可。改进:可直接用一个辅助字符串模拟栈,最后无需倒序直接返回该字符串即可。
代码
class Solution {
public:
string removeDuplicates(string s) {
string result;
for (char t : s) {
if (result.empty() || result.back() != t) {
result.push_back(t);
} else {
result.pop_back();
}
}
return result;
}
};
复杂度
时间复杂度:O(n)
空间复杂度:O(1),返回值不计入空间复杂度
Leetcode150 逆波兰表达式求值
题目链接:逆波兰式表达式求值
思路
逆波兰式即后缀表达式,其求值为栈的经典应用,408中也常见,遇到数就入栈,遇到操作符op便从栈顶依次弹出两个数nums1和nums2,执行nums2 op nums1后将结果再入栈,遍历后栈内的唯一元素即为表达式结果。注:因数据运算规模较大,栈需要用到long long类型。
代码
class Solution {
public:
int evalRPN(vector<string>& tokens) {
// 力扣修改了后台测试数据,需要用longlong
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])); //stoll将字符串转成long long类型
}
}
int result = st.top(); //栈内最后一个元素即为结果
st.pop();
return result;
}
};
复杂度
时间复杂度:O(n)
空间复杂度:O(1)