代码随想录day10 栈与队列01
小学期加上实习加上学校的机器人比赛,导致前面的题目刷完了但是根本没有时间写博客,今天属于忙里偷闲,继续干
- 用栈实现队列
https://leetcode.cn/problems/implement-queue-using-stacks/
一道模拟类的题目,由于栈是先进后出,所以具有翻转顺序的作用,而队列是先进先出,因此只要用两个栈就可以实现队列,一个输入stIn,一个输出stOut,需要注意的是,不能盲目的直接将stIn的元素push进stOut,应该等到stOut里边的元素为空,再一次性将stIn的元素push进入stOut,否则还是会是的顺序错乱。
点击查看代码
class MyQueue {
public:
stack<int> stIn;
stack<int> stOut;
/** Initialize your data structure here. */
MyQueue() {
}
/** Push element x to the back of queue. */
void push(int x) {
stIn.push(x);
}
/** Removes the element from in front of queue and returns that element. */
int pop() {
// 只有当stOut为空的时候,再从stIn里导入数据(导入stIn全部数据)
if (stOut.empty()) {
// 从stIn导入数据直到stIn为空
while(!stIn.empty()) {
stOut.push(stIn.top());
stIn.pop();
}
}
int result = stOut.top();
stOut.pop();
return result;
}
/** Get the front element. */
int peek() {
int res = this->pop(); // 直接使用已有的pop函数
stOut.push(res); // 因为pop函数弹出了元素res,所以再添加回去
return res;
}
/** Returns whether the queue is empty. */
bool empty() {
return stIn.empty() && stOut.empty();
}
};
- 用队列实现栈
https://leetcode.cn/problems/implement-stack-using-queues/
一道模拟类的题目,队列一直是先进先出,没有翻转顺序的作用,不可能用两个队列去实现一个栈,但是我们可以将最后一个进入的元素的前面的所有元素pop之后再push进入队列,这样最后一次pop的时候弹出的一定就是最后一个元素,那么每一次我们弹出元素都这么做,就实现了元素的后进先出,这就是一个栈。
点击查看代码
class MyStack {
public:
queue<int> que1;
queue<int> que2; // 辅助队列,用来备份
/** Initialize your data structure here. */
MyStack() {
}
/** Push element x onto stack. */
void push(int x) {
que1.push(x);
}
/** Removes the element on top of the stack and returns that element. */
int pop() {
int size = que1.size();
size--;
while (size--) { // 将que1 导入que2,但要留下最后一个元素
que2.push(que1.front());
que1.pop();
}
int result = que1.front(); // 留下的最后一个元素就是要返回的值
que1.pop();
que1 = que2; // 再将que2赋值给que1
while (!que2.empty()) { // 清空que2
que2.pop();
}
return result;
}
/** Get the top element.
** Can not use back() direactly.
*/
int top(){
int size = que1.size();
size--;
while (size--){
// 将que1 导入que2,但要留下最后一个元素
que2.push(que1.front());
que1.pop();
}
int result = que1.front(); // 留下的最后一个元素就是要回返的值
que2.push(que1.front()); // 获取值后将最后一个元素也加入que2中,保持原本的结构不变
que1.pop();
que1 = que2; // 再将que2赋值给que1
while (!que2.empty()){
// 清空que2
que2.pop();
}
return result;
}
/** Returns whether the stack is empty. */
bool empty() {
return que1.empty();
}
};
- 有效的括号
https://leetcode.cn/problems/valid-parentheses/
由于栈本身先进后出的特点,使得栈非常适合用来解决对称性的问题,本题就是一道非常经典的栈相关题目。
首先遇到左括号的时候将与之对应的右括号push进栈中,为什么是右括号呢,因为等我们去判断匹配的时候只需要判断输入的括号和弹出的相等与否即可,不需要再做其他的操作,简化了判断操作;第二,判断错误有三种情况,弹出之前判断栈empty时发现栈是空的,说明右括号多了;发现遍历完字符串之后栈不为空,说明左括号多了;发现此时遍历的右括号和栈弹出的不匹配,说明是括号的类型匹配补上。到此,这道题就做完了。
点击查看代码
class Solution {
public:
bool isValid(string s) {
if (s.size() % 2 != 0) return false; // 如果s的长度为奇数,一定不符合要求
stack<char> 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(']');
// 第三种情况:遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号 return false
// 第二种情况:遍历字符串匹配的过程中,发现栈里没有我们要匹配的字符。所以return false
else if (st.empty() || st.top() != s[i]) return false;
else st.pop(); // st.top() 与 s[i]相等,栈弹出元素
}
// 第一种情况:此时我们已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false,否则就return true
return st.empty();
}
};
- 删除字符串中的相邻元素
https://leetcode.cn/problems/remove-all-adjacent-duplicates-in-string/
这个问题的难点在于,首先,我们需要有个容器来存储之前的元素,不然我们怎么知道当中间的重复元素消除之后,两侧的元素拼接之后会不会再次出现重复的元素呢;第二,根据题目的要求,之后出现的重复元素也需要弹出,所以,这个容器必须具备这个能力,我们很自然的就想到了栈。这也是用栈解决的经典问题。
点击查看代码
class Solution {
public:
string removeDuplicates(string S) {
stack<char> st;
for (char s : S) {
if (st.empty() || s != st.top()) {
st.push(s);
} else {
st.pop(); // s 与 st.top()相等的情况
}
}
string result = "";
while (!st.empty()) { // 将栈中元素放到result字符串汇总
result += st.top();
st.pop();
}
reverse (result.begin(), result.end()); // 此时字符串需要反转一下
return result;
}
};