个人认为自己关于C++中栈、队列这一部分没有学的很好,周日趁着不打卡了补齐这个学习进程。感觉还是要搞清楚STL当中的原理才算是真正学会这一相关的内容。
1)有效的括号
对于一个完整的且满足要求的字符串,要去判断它正确,则可以遇到左括号时像栈内压入右括号,当遇到下一个字符则将栈顶元素与这个字符比较,如果不是则返回false,如果是则弹出这个元素,直到栈空。
首先分析好出现不匹配的几种情况:
(1)可能是字符串里左方向的括号多余了,所以不匹配。这种情况会发现栈不为空,此时有相应的左括号没有右括号来进行匹配。
(2)可能是字符串里右方向的括号多余了,所以不匹配。此时栈空,但是已经没有匹配的字符了,说明全都匹配了。
(3)括号没有多余,但是匹配错误。也就是在遍历字符串匹配的过程当中,发现栈里没有要匹配的字符。
class Solution {
public:
bool isValid(string s) {
if(s.size() & 2 != 0) return false;
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();
}
return st.empty();
}
};
2)删除字符串中的所有重复元素
这道题的思路还是蛮简单的,可以按照顺序遍历元素,如果遍历的这个元素和栈顶的元素相同,那么执行弹出栈顶元素,顺便遍历到下一个元素。否则放入栈内。最后弹出栈内所有元素,对字符串进行翻转即可。
class solution{
public:
string removeDuplicates(string S){
stack<char> st;
for(char s : S){
if(st.empty() || s!=st.top()){
st.push(s);
}
else{
st.pop();
}
}
string result = "";
while(!st.empty()){
result += st.top();
st.pop();
}
reverse(result.begin().result.end());
return result;
}
3) 逆波兰表达式
逆波兰表达式:
逆波兰表达式是一种后缀表达式,所谓后缀就是指算符写在后面。
平常使用的算式则是一种中缀表达式,如 ( 1 + 2 ) * ( 3 + 4 ) 。
该算式的逆波兰表达式写法为 ( ( 1 2 + ) ( 3 4 + ) * ) 。
逆波兰表达式主要有以下两个优点:
去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + * 也可以依据次序计算出正确结果。
适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中
class Solution {
public:
int evalRPN(vector<string>& tokens) {
stack<int> st;
for(const string& token : tokens){
if(string("+-*/").find(token) != string::npos){
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(token));
//stoi 是 C++ 标准库中的一个函数,用于将字符串转换为整数。
}
}
int result = st.top();
st.pop(); // 把栈里最后一个元素弹出(其实不弹出也没事)
return result;
}
};