代码随想录训练营day10()
20. 有效的括号
题目
思考历程
把左括号放到栈里,如果遇到右括号,就与预期的右括号对比。
解题方法(相邻两个括号配对就消除)
巧妙:遇到左括号时,把预期的右括号放到栈里(简化了比较流程)
只需要比较当前元素和栈顶相不相等,比左括号先入栈代码实现要简单得多
- 流程
- 遍历字符串
- 如果是左括号:就把相应的右括号入栈
- 如果是右括号:就判断三种异常情况:
- 左括号多了(遍历完才知道)
- 匹配失败(未遍历完,待检测元素与栈顶元素不相等)
- 右括号多了(未遍历完,栈里已空)
- 正常情况:待检测元素与栈顶元素相等,匹配成功
难点
犯错:匹配成功后,记得弹出(消消乐)
犯错:判断判断栈是否为空,要在判断元素是否等于栈顶之前(空栈无栈顶,会出错)
代码
class Solution {
public:
bool isValid(string s) {
stack<int>sta;
if(s.size()%2!=0){
return false;
}
for(int i = 0; i<s.size(); i++){
//左括号决定入栈
if(s[i] == '(') sta.push(')');
else if(s[i] == '{') sta.push('}');
else if(s[i] == '[') sta.push(']');
else if(sta.empty()) return false;//情况三:右括号多了
else if(s[i] != sta.top()) return false;//情况二:右括号和左括号匹配失败
else sta.pop();//匹配成功,要弹出
}
return sta.empty();//情况一:左括号多了
}
};
1047. 删除字符串中的所有相邻重复项
题目
匹配问题都是栈的强项
思考历程
像消消乐一样。
解题方法(相邻两个字母相等就消除)
- 巧妙:拿字符串直接作为栈(对字符串进行push_back和pop_back,因为本题要返回修改后的字符串,所以这样做省去了栈转字符串)
- 流程:
1、新建接收结果的字符串 result
2、遍历字符串元素i,如果result为空,或者i与栈顶不匹配,就把i“进栈”
3、如果匹配上了,就把栈顶弹出
4、最后返回result字符串
难点
- 何时能把字符串作为栈:在字符串的尾部添加字符(进栈),并从尾部删除字符(出栈),同时通过back方法访问栈顶元素,就像栈的操作一样。
- string和vector类似,有尾部操作方法push_back和pop_back,没有对应的头部操作方法。
- string是一个字符序列容器,其中每个元素都是一个char字符。
代码
class Solution {
public:
string removeDuplicates(string s) {
string result;
for(char i:s){
if(result.empty()||i!=result.back()){
result.push_back(i);
}
else result.pop_back();
}
return result;
}
};
150. 逆波兰表达式求值
题目
解题方法(运算符+栈顶两个数)
流程:
- 遍历字符串
- 如果是数字,就入栈
- 如果是运算符,就把栈顶的两个元素弹出来运算,然后把结果入栈
- 最后的栈顶st.top()就是结果
难点
- 犯错:减法、除法有顺序要求,是老元素-新元素,而nums2才是老元素
- 犯错:string强制转int出错,要用到stoi函数
代码
class Solution {
public:
stack<int>st;
int evalRPN(vector<string>& tokens) {
for(int i=0; i<tokens.size(); i++){
if(tokens[i]=="+"||tokens[i]=="-"||tokens[i]=="*"||tokens[i]=="/"){
int nums1 = st.top();
st.pop();
int nums2 = st.top();
st.pop();
if(tokens[i]=="+"){
st.push(nums2+nums1);
}
if(tokens[i]=="-"){
st.push(nums2-nums1);
}
if(tokens[i]=="*"){
st.push(nums2*nums1);
}
if(tokens[i]=="/"){
st.push(nums2/nums1);
}
}
else{
st.push(stoi(tokens[i]));
}
}
return st.top();
}
};
栈的三道题总结(相邻匹配)
栈擅长处理的情况:相邻匹配
1、相邻匹配的左、右括号({}),就消除
2、相邻的相同小写字母abba,就消除
3、相邻的两个数字及一个运算符(12+34+*),就执行运算