《代码随想录》栈和队列
题目:用栈实现队列
我这里把stIn作为了主栈,stOut作为了辅助栈,而《代码随想录》则是导入到stOut就不管了,这样反而能在peek代码中复用,但我的好理解
class MyQueue {
public:
stack<int> stIn;
stack<int> stOut;
MyQueue() {
}
void push(int x) {
stIn.push(x);
}
int pop() {
while (!stIn.empty()) {
int node = stIn.top();
stIn.pop();
stOut.push(node);
}
int result = stOut.top();
stOut.pop();
while (!stOut.empty()) {
int node = stOut.top();
stOut.pop();
stIn.push(node);
}
return result;
}
int peek() {
while (!stIn.empty()) {
int node = stIn.top();
stIn.pop();
stOut.push(node);
}
int result = stOut.top();
while (!stOut.empty()) {
int node = stOut.top();
stOut.pop();
stIn.push(node);
}
return result;
}
bool empty() {
return stIn.empty() && stOut.empty();
}
};
题目:用队列实现栈
或者top()函数直接用que.back即可
class MyStack {
public:
queue<int> que;
MyStack() {
}
void push(int x) {
que.push(x);
}
int pop() {
int size = que.size() - 1;
while (size--) {
que.push(que.front());
que.pop();
}
int result = que.front();
que.pop();
return result;
}
int top() {
int result = this->pop();
que.push(result);
return result;
}
bool empty() {
return que.empty();
}
};
题目:有效的括号
class Solution {
public:
bool isValid(string s) {
//思路:首先判断是不是左边的括号,如果是左边的括号,去在栈中分别加入对应的右边的括号,然后只要一遇到不是左边括号的,那就是判断右边的和栈里已经有的右边括号匹配不匹配,如果匹配,那就出栈
//true的结果:遍历完以后,如果栈是空,那就是都是有效的括号
//错误1:如果栈最后剩下了,那就是左括号多了
//错误2:如果还没遍历完s,栈就没了,那就是右括号多了
//错误3:如果是没匹配上,那就是不匹配
stack<char> st;
for (char ss : s) {
if (ss == '(') {
st.push(')');
} else if (ss == '[') {
st.push(']');
} else if (ss == '{') {//上面是针对三种不同的左边括号把右边括号加入栈
st.push('}');
} else if (st.empty()) {//错误2:数组还有,但是栈没了
//注意,这里应该把st.empty的函数写在前面,为什么呢?因为后面还有st.top的函数,如果栈为空,但是用了st.top函数,就会报错,因此应该先判断栈空
return false;
} else if (ss != st.top()) {//错误3:没匹配上
return false;
} else if (ss == st.top()) {//是有效的括号,那就要出栈
st.pop();
}
}
if (st.empty()) {//全是有效的括号,那就是true
return true;
} else {//错误1:数组没了,但是栈还有
return false;
}
}
};
题目:删除字符串中的所有相邻重复项
class Solution {
public:
string removeDuplicates(string s) {
//思路:其实就是对对碰,我先遍历这个数组,如果这个数组的该元素能匹配上栈的top元素,那就消掉(即出栈),如果匹配不上,放入栈中
//消完了以后遇到第二个问题,这是个栈,但是他要的是个字符串,栈应该如何转化为字符串,可以用加号运算符拼接字符串,然后反转一下,这样时间复杂度是
stack<char> st;
for (char ss : s) {
if (st.empty() || ss != st.top()) {//如果匹配不上,放入栈中
st.push(ss);
} else {//如果这个数组的该元素能匹配上栈的top元素,那就消掉(即出栈)
st.pop();
}
}
string result = "";
while (!st.empty()) {
result += st.top();
st.pop();
}
reverse(result.begin(), result.end());
return result;
}
};
更近一步,可以直接用vector来模拟栈,代码如下
class Solution {
public:
string removeDuplicates(string s) {
string result;
for (char ss : s) {
if (result.empty() || ss != result.back()) {
result.push_back(ss);
} else {
result.pop_back();
}
}
return result;
}
};
题目:逆波兰表达式求值
class Solution {
public:
int evalRPN(vector<string>& tokens) {
//去遍历这个数组如果不是符号(即数字),那就去加入到栈中,然后一旦遍历到符号,那就从栈中取出来两个数,然后做了运算以后的结果又放入栈中,最后算出来多少就是多少
stack<int> st;
for (string s : tokens) {
if (s != "+" && s != "-" && s != "*" && s != "/") {//如果是数字,那就放进去栈中
st.push(stoi(s));
} else {
//拿出来这两个数字
int num1 = st.top();
st.pop();
int num2 = st.top();
st.pop();
int res;//定义出来两个数的运算结果
if (s == "+") {
res = num2 + num1;
} else if (s == "-") {
res = num2 - num1;
} else if (s == "*") {
res = num2 * num1;
} else if (s == "/") {
res = num2 / num1;
}
st.push(res);//把结果最后放进去栈
}
}
return st.top();
}
};
题目:滑动窗口最大值
题目:前K个高频元素
总结:用栈实现匹配问题
总结:栈中的字符怎么变成一个字符串
利用加号运算符来拼接,然后反转(从《题目:删除字符串中的所有相邻重复项》学到的)
string result = "";
while (!st.empty()) {
result += st.top();
st.pop();
}
reverse(result.begin(), result.end());
总结:队列解决的是什么样的问题
总结:优先级队列
这个很适合求前K个最大值这种问题,链接:《堆排序》二叉树的题目中《二叉搜索树中的众数》也是类似的,可以理解成这些元素的,出现频率最高的第一个元素,而这个问题中其实我用的是把map转化为vector,然后排了序