232.用栈实现队列
队列是FIFO,栈是FILO;两个栈可以实现一个队列,先进后出+ 后进先出 = 先进先出。比如说第一个栈插入(1 2 3),另一个栈接受前一个弹出来的数(3 2 1)
class MyQueue {
public:
stack<int> stkIn;
stack<int> stkOut;
MyQueue() {
}
void push(int x) {
stkIn.push(x);
}
int pop() {
if(stkOut.empty()) {
while(!stkIn.empty()) {
int tmp = stkIn.top();
stkIn.pop();
stkOut.push(tmp);
}
}
int res = stkOut.top();
stkOut.pop();
return res;
}
int peek() {
//虽然复用了代码但是额外了数据移动的开销。
int res = this->pop();
stkOut.push(res);
return res;
}
bool empty() {
return stkIn.empty() && stkOut.empty();
}
};
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue* obj = new MyQueue();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->peek();
* bool param_4 = obj->empty();
*/
225. 用队列实现栈
这道题没有那么直观,思想是除了队列尾部的元素暂时保存到另一个容器(可用vector等其他容器)中,目的是把原来队列尾部的元素置于队列头部,这样队列就能处理它。再把队列尾部的元素pop掉,最后把其他元素再重新按照顺序加入回来。更加优化的做法是使用一个队列处理情况。本题可以参照代码随想录的动态图,知道模拟的思路后代码一目了然。
class MyStack {
public:
queue<int> queInt;
queue<int> queOut;
MyStack() {
}
void push(int x) {
queInt.push(x);
}
int pop() {
int size = queInt.size();
size--;
int b;
while(size--) {
queOut.push(queInt.front());
queInt.pop();
}
int a = queInt.front();
queInt.pop();
queInt = queOut;
while(!queOut.empty()) {
queOut.pop();
}
return a;
}
int top() {
int x = this->pop();
queInt.push(x);
return x;
}
bool empty() {
return queInt.empty();
}
};
/**
* Your MyStack object will be instantiated and called as such:
* MyStack* obj = new MyStack();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->top();
* bool param_4 = obj->empty();
*/
下面是优化后的代码:
class MyStack {
public:
queue<int> que;
MyStack() {
}
void push(int x) {
que.push(x);
}
int pop() {
int size = que.size();
size--;
while(size--) {
this->push(que.front());
que.pop();
}
int result = que.front();
que.pop();
return result;
}
int top() {
int x = this->pop();
que.push(x);
return x;
}
bool empty() {
return que.empty();
}
};
/**
* Your MyStack object will be instantiated and called as such:
* MyStack* obj = new MyStack();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->top();
* bool param_4 = obj->empty();
*/
20. 有效的括号
此题要求左边括号按顺序匹配右边括号,因为是左边括号必须在右边括号前,很容易想到栈的特点FILO。我采取了配对关系映射的方法。
#include <stack>
#include <unordered_map>
#include <string>
using namespace std;
class Solution {
public:
bool isValid(string s) {
// 如果字符串长度为奇数,直接返回 false
if (s.size() % 2 != 0) return false;//!优先级大于%,不能写成(!s.size()%2)的形式
// 配对关系映射
unordered_map<char, char> umap = {
{')', '('},
{'}', '{'},
{']', '['}
};
stack<char> stk;
for (char ch : s) {
if (umap.count(ch)) {
if (stk.empty() || stk.top() != umap.at(ch)) {
return false;
}
stk.pop();
} else {
stk.push(ch);
}
}
return stk.empty();
}
};
1047. 删除字符串中的所有相邻重复项
此题和上一题类似,也是运用了栈的特性消除重复项,判定条件:不重复的元素将其插入,若相邻元素重复则一起消除。注意的点是栈归类为container adapter,不属于容器本身(队列也是),所以无法直接把它转化为其他容器,所以元素只能遍历访问。
class Solution {
public:
string removeDuplicates(string s) {
stack<char> stk;
for(char ch:s) {
if(!stk.empty() && ch == stk.top()) {
stk.pop();
}else {
stk.push(ch);
}
}
string res;
while(!stk.empty()) {
res+=stk.top();
stk.pop();
}
reverse(res.begin(),res.end());
return res;
}
};