代码随想录【day 11 栈与队列】| 20. 有效的括号 1047. 删除字符串中的所有相邻重复项 150. 逆波兰表达式求值
LeetCode 20. 有效的括号
题目链接:20.有效的括号
卡哥文解
视频讲解
- 题目描述: 给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
解题思路 (栈的经典应用)
1、遍历字符串 遇到左方向的括号将对应的右方向括号压入栈
在遍历时 将字符串遇到的右方向括号和压入的右方向括号进行匹配
若相同则消去 遇到以下三种情况 则return false
2、不匹配的情况:左括号多了 / 右括号多了 / 括号不匹配
- 左括号多:字符串遍历完 栈不为空
- 括号类型不匹配:栈顶元素 top 和右方向的括号类型不匹配; (例如:[ { ( } ] 压入栈为 ) } ])
- 右括号多:字符串没遍历完 栈为空
3、剪枝:如果字符串的长度为奇数,一定不有效
实现难点
1、空栈取栈顶元素会报异常
2、当右方向括号和压入的右方向括号进行匹配时,将栈顶元素弹出
代码实现
class Solution {
public:
stack <char> st;
bool isValid(string s) {
if(s.size() %2 != 0)return false;
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();
}
// 若字符串遍历完 栈不为空 返回false
return st.empty();
}
};
LeetCode 1047. 删除字符串中的所有相邻重复项
题目链接:LeetCode1047.删除字符串中的所有相邻重复项
卡哥文解
视频讲解
- 题目描述: 给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
- 在 S 上反复执行重复项删除操作,直到无法继续删除。
- 在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
解题思路
- 利用栈存放遍历过的元素,当遍历当前元素时,去栈中查看是否遍历过相同数值的相邻元素
实现难点
- 不仅删除相邻项 若删除之后又有相连处 还要继续删除
- 若用栈实现 返回最终结果时 栈内元素和结果字符串相反 还需要反转一下
故还可以直接使用字符串模拟栈
- 取字符串尾部 :
result.back()
将元素放到字符串的尾部:result.push_back();
代码实现1(直接利用栈)
class Solution {
public:
string removeDuplicates(string s) {
stack<char>st;
// 加元素的情况 当栈为空 或者 栈顶元素与字符串遍历元素不相等时
for(int i=0;i<s.size();i++){
if(st.empty() || st.top()!=s[i]) st.push(s[i]);
else st.pop();
}
string result;
// 先取top 再弹出
while(!st.empty()){
result += st.top();
st.pop();
}
reverse(result.begin(), result.end());
return result;
}
};
代码实现2(字符串模拟栈)
class Solution {
public:
string removeDuplicates(string S) {
string result;
for(char s : S) {
if(result.empty() || result.back() != s) {
result.push_back(s);
}
else {
result.pop_back();
}
}
return result;
}
};
LeetCode 150. 逆波兰表达式求值
题目链接:150.逆波兰表达式求值
卡哥文解
视频讲解
- 题目描述: 给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。
- 请你计算该表达式。返回一个表示表达式值的整数。
- 注意:
- 有效的算符为 ‘+’、‘-’、‘*’ 和 ‘/’ 。
- 每个操作数(运算对象)都可以是一个整数或者另一个表达式。
- 两个整数之间的除法总是 向零截断 。
- 表达式中不含除零运算。
- 输入是一个根据逆波兰表示法表示的算术表达式。
- 答案及所有中间计算结果可以用 32 位 整数表示。
解题思路
1、逆波兰表达式是后缀表达式,直接根据顺序处理而不需要考虑括号优先级
2、遇到数字则入栈,遇到运算符则取出栈顶两个数字进行计算,并将计算结果压入栈中。
(补:当vector当作形参输入到函数时,可以加& 或者不加)
带&表示传入函数的是vector的引用(即物理位置),函数内部对vector改动,vector就会改变;
不带&表示传入的是vector的复制品(开辟了另一块位置),函数内部对其改动,不会影响原本的vector;
vector< int> nums:nums是一个容器变量,容器名称为vector,容器内存的数据为int型
vector< int> &nums:nums为一个引用,引用的内容是vector这个容器内部存放的整型数据
实现难点
1、怎么样 实现将操作数进行运算:对四个运算符再分别进行讨论
2、因为向栈里添加元素的情况较复杂 所以可以先讨论 遇到操作符进行的运算 else下添加元素
3、在进行减法以及除法操作时,弄清操作数的位置
4、读入的是字符串 在添加数字入栈时 需调用stoll:将字符串转换为long long
代码实现
class Solution {
public:
int evalRPN(vector<string>& tokens) {
stack<int>st;
for(int i=0;i<tokens.size();i++){
// 向栈里添加元素 栈为空以及没有遇到操作符
if(tokens[i]=="+" ||tokens[i]=="-" || tokens[i]=="*" || tokens[i]=="/"){
int opre1 = st.top();
st.pop();
int opre2 = st.top();
st.pop();
// 怎么样 实现将操作数进行运算 对四个运算符分别讨论
if(tokens[i] == "+") st.push(opre1+opre2);
if(tokens[i] == "-") st.push(opre2-opre1);
if(tokens[i] == "*") st.push(opre1*opre2);
if(tokens[i] == "/") st.push(opre2/opre1); //弄清楚谁是除数
}
else{
st.push(stoll(tokens[i]));
}
}
return st.top();
}
};
补充
push与 push_back都是向数据结构中添加元素
push_back() 在Vector最后添加一个元素(参数为要插入的值)
pop_back()删除vector容器中的最后一个元素
vector<int> vi;
C++ vector 排序 sort(vi.begin(),vi.end()); // 从小到大
反转 reverse(vi.begin(),vi.end());// 从大到小
查找 find(vi.begin(),vi.end(),3);
定义stack 对象的示例代码如下:
stack<int> s1;
stack<string> s2;
stack 的基本操作有:
入栈,如例:s.push();在栈顶增加元素
出栈,如例:s.pop();注意,出栈操作只是删除栈顶元素,并不返回该元素。
访问栈顶,如例:s.top()
判断栈空,如例:s.empty(),当栈空时,返回true。
访问栈中的元素个数,如例:s.size()。
queue 的基本操作有:
入队,如例:q.push(x); 将x 接到队列的末端。
出队,如例:q.pop(); 弹出队列的第一个元素,注意,并不会返回被弹出元素的值。
访问队首元素,如例:q.front(),即最早被压入队列的元素。
访问队尾元素,如例:q.back(),即最后被压入队列的元素。
判断队列空,如例:q.empty(),当队列空时,返回true。
访问队列中的元素个数,如例:q.size()
day11总结复盘
1、栈结构的特殊性 非常适合做对称匹配 或者 相邻字母的特殊判断(左括号 右括号匹配 或者 相同 或者符合 遇到操作符进行操作再压入)
2、企业项目开发尽量不要使用 递归! 项目较大时,由于参数多,全局变量等,使用递归很容易判断不充分return条件,容易无限递归(或递归层级过深),造成栈溢出错误。
3、学会C++的一种循环简便写法 for(Char s:S)
则s是逐个取出的字符
参考链接
https://blog.csdn.net/u013630349/article/details/46853297
https://blog.csdn.net/qq_52876054/article/details/119270241?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7ERate-2-119270241-blog-121026264.pc_relevant_aa&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7ERate-2-119270241-blog-121026264.pc_relevant_aa&utm_relevant_index=3
https://blog.csdn.net/leviopku/article/details/121026264