一、有效的括号
20.有效的括号
感觉做了很多次了。很经典的使用栈问题。
抓住关键,不匹配的场景只有三种情况:
遇到左括号,就把对应的右括号压入栈中。(这样压入是为了出栈时更好的匹配)
遇到右括号,就开始与栈顶的元素进行匹配了。
我们再来看看结束条件是啥样的:
class Solution
{
public:
bool isValid(string s)
{
// 可以剪枝
if (s.size() % 2 != 0)
return false;
stack<int> 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() || s[i] != st.top())
{
return false;
}
else // 这就是正常的匹配的情况!!消除的过程
st.pop();
}
//第一种情况:此时我们已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配
return st.empty();
}
};
1、else if (st.empty() || s[i] != st.top())?
严谨一点,因为s[i] != st.top() && st.empty()
这样的话,容易先操作了空栈!
二、删除字符串中的所有相邻重复项
1047.删除字符串中的所有相邻重复项
这个栈,用来存放我们遍历过的元素,因为只有这样才能最方便的知道或者记录上一个遍历过的元素是啥。
这个题很像 括号匹配 这个题。
class Solution
{
public:
string removeDuplicates(string s)
{
stack<char> st;
string res;
for (auto e : s)
{
if (st.empty() || e != st.top())
{
st.push(e);
}
else
{
st.pop();
}
}
while (!st.empty())
{
res += st.top();
st.pop();
}
reverse(res.begin(), res.end());
return res;
}
};
当然可以拿字符串直接作为栈,这样省去了栈还要转为字符串的操作。
// 不使用栈,直接用string模拟
class Solution
{
public:
string removeDuplicates(string s)
{
string res;
for (auto e : s)
{
if (res.empty() || e != res.back())
{
res.push_back(e);
}
else
{
res.pop_back();
}
}
return res;
}
};
三、逆波兰表达式求值
后缀表达式就是逆波兰表达式。
我们看着比较舒服的,正常的就叫做中缀表达式。
中序遍历的结果:1 + 3 X 4 +5
存在的问题就是,一定要加括号,才能保证运算结果的正确性!
但是后缀表达式,我们就不需要加括号。计算机自己去顺序处理就可以了。
用栈模拟:
遇见数字,就入栈;遇见符号,就拿栈里面就近的两个数字计算,然后再次入栈。
这个操作的实质也是 “消除” ,只不过是拿两个元素来新“计算”得到新值。
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 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(atoi(tokens[i].c_str()));
}
}
int res = st.top();
st.pop();
return res;
}
};
注意num1和num2的运算顺序,是num1除num2,还是num2除num1。