代码随想录Day 11| 20. 有效的括号1047. 删除字符串中的所有相邻重复项150. 逆波兰表达式求值
有效的括号
文档讲解:代码随想录
视频讲解: 栈的拿手好戏!| LeetCode:20. 有效的括号
状态:√
- 可能无效的情况
a. (] 左括号和右括号不匹配 或者 [(]) 没有按顺序闭合
b. [[()] 缺少匹配的括号 - 解决方法
对于第二种情况我们可以直接通过字符串长度是不是2的倍数来解决一部分情况
对于第一种情况,我们可以遍历字符串,当遇到左括号就压入堆栈,遇到右括号就拿出堆栈的栈顶元素进行匹配,如果一直能够匹配知道栈为空,那么就说明是有效的 - 注意的点
在对栈进行取值操作的时候要先判断栈此时是否为空。
最后的返回值还需要判断栈是否为空,这是为了解决情况b出现的遗漏情况比如[[[[
class Solution {
public:
bool isValid(string s) {
if(s.size()%2!=0 || s[0] == ')' || s[0] == '}' || s[0] == ']')
{
return false;
}
else
{
stack<char> stk;
for(int i = 0;i<s.size();i++)
{
if(s[i] == '(' || s[i] == '{' || s[i] == '[')
{
stk.push(s[i]);
}
else if(s[i] == ')')
{
if(stk.empty()||stk.top()!='(')
{
return false;
}
stk.pop();
}
else if(s[i] == '}')
{
if(stk.empty()||stk.top()!='{')
{
return false;
}
stk.pop();
}
else if(s[i] == ']')
{
if(stk.empty()||stk.top()!='[')
{
return false;
}
stk.pop();
}
}
if(stk.empty()) return true;
else return false;
}
}
};
遇到左括号压入对应的右括号,可以简化判断
删除字符串中的所有相邻重复项
文档讲解:代码随想录
视频讲解: 栈的好戏还要继续!| LeetCode:1047. 删除字符串中的所有相邻重复项
状态:√
- 双指针
类似删除数组的重复项那道题,只不过这道题是全部删除,那么可能会导致删除之后原本不是相邻的元素相邻了。导致又出现重复项。所以每次遇见重复项删除后需要将左指针回退一格。
注意此时左指针可能为-1即第一个元素重复了,那么下一次右指针就不需要判断了而是直接给字符串的第一个元素赋值即可
class Solution {
public:
string removeDuplicates(string s) {
//初始化left为-1
int left=-1;
for(int i=0;i<s.size();i++)
{
//当右指针与左指针对应的值相等时,左指针回退
if(left>=0&&s[i]==s[left])
{
left--;
}
//首先是给第一个元素赋值,之后就是如果不等则赋值
else
{
s[++left] = s[i];
}
}
s.resize(left+1);
return s;
}
};
- 栈的使用
将元素压入栈中,除了第一个元素之后每个元素的压入先判断是否与栈顶元素相等,如果相等两个都丢掉。最后符合条件的就是栈中的元素。
class Solution {
public:
string removeDuplicates(string s) {
stack<char> stk;
for(int i=0;i<s.size();i++)
{
if(stk.empty()||s[i]!=stk.top())
{
stk.push(s[i]);
}
else
{
stk.pop();
}
}
s.resize(stk.size());
for(int i=stk.size()-1;i>=0;i--)
{
s[i] = stk.top();
stk.pop();
}
return s;
}
};
对栈的操作记得要检测栈是否为空,否则pop很容易出错。
逆波兰表达式求值
文档讲解:代码随想录
视频讲解: 栈的最后表演! | LeetCode:150. 逆波兰表达式求值
状态
本来想继续使用双指针,原理就是left与right同时移动,然后当right遇到符号时,left-2和left-1调用运算,将值存储在left-2的位置。然后left,right++
最开始就是使用它的原始vector,结果他是一个string的容器,所以最好还是再新建一个list或者容器来存储值吧。
下面使用栈来做,就是没遇到运算符之前,压入栈,当遇到了取出前两个元素然后计算后再压入堆栈,知道容器遍历完,返回栈中的唯一元素。
需要注意的是减法和除法操作,先去出来的是操作数
class Solution {
public:
int evalRPN(vector<string>& tokens) {
stack<long long> stk;
int i = 0;
while(i<tokens.size())
{
if(tokens[i] == "+" ||tokens[i] == "-" ||tokens[i] == "*" ||tokens[i] == "/" )
{
long long num1 = stk.top();
stk.pop();
long long num2 = stk.top();
stk.pop();
if(tokens[i] == "+")
{
stk.push(num1+num2);
}
else if(tokens[i] == "*")
{
stk.push(num1*num2);
}
else if(tokens[i] == "-")
{
stk.push(num2-num1);
}
else if(tokens[i] == "/")
{
stk.push(num2/num1);
}
}
else
{
stk.push(stoll(tokens[i]));
}
i++;
}
return stk.top();
}
};





