`
代码随想录第十一天 | LeetCode 232.用栈实现队列 225.用队列实现栈
前言
用数组模拟栈:
// tt表示栈顶
int stk[N], tt = 0;
// 向栈顶插入一个数
stk[ ++ tt] = x;
// 从栈顶弹出一个数
tt -- ;
// 栈顶的值
stk[tt];
// 判断栈是否为空,如果 tt > 0,则表示不为空
if (tt > 0)
{
}
数组模拟队列
// hh 表示队头,tt表示队尾(插入和删除都是++操作)
int q[N], hh = 0, tt = -1;
// 向队尾插入一个数
q[ ++ tt] = x;
// 从队头弹出一个数
hh ++ ;
// 队头的值
q[hh];
// 判断队列是否为空,如果 hh <= tt,则表示不为空
if (hh <= tt)
{
}
一、LeetCode 232.用栈实现队列
题目解析:用栈来实现队列,因为栈是只有一个开口,但是队列却又两个开口。又因为顺序的问题,1.2.3.的进,就应该1.2.3.的出来.因此我们需要用到另一个栈。进两边栈,相当于顺序就不变了。哇塞,又是那个经典逻辑的逻辑,反转两次然后顺序正常。这里的顺序就是指的是第一次进栈,出来的会是反的顺序,那进两次栈就刚好可以调整顺序。
代码实现:定义一个入栈,一个出栈。stackin,stackout。入栈push(x)。放进出栈:判断入栈是否为空,然后while循环用出栈把入栈中的所有元素吸收。最后在进行出栈的弹出元素就好了。
C++代码ruxia
class MyQueue {
public:
//用到两个栈
stack<int> stIn;//入栈
stack<int> stOut;//出栈
MyQueue() {
}
//入栈弹入元素
void push(int x) {
stIn.push(x);
}
//放进出栈元素并且返回头部
int pop() {
// 先判断是不是有数据 ,不要直接往里放。
if (stOut.empty()) {
// 只有当stOut为空的时候,再从stIn里导入数据(导入stIn全部数据)
//这里其实还可以更加深入的去思考一下,就是为什么一定要stOut栈为空的时候我们才可以添加
//因为栈是先进先出,转换出的队列也要先进先出,但是你一旦把stIn栈的元素放到stOut栈中,新放入的元素就会更快的出来,就改变了顺序。
while(!stIn.empty()) {
stOut.push(stIn.top());//这就是stIn导入到stOut数据中
stIn.pop();//导入一个弹出去一个。其次也是说判断条件一定要移动,不然会无限循环。
}
}
int result = stOut.top();//将头部(接口)赋给result
stOut.pop();
return result;
}
//只需要返回头部就好了,不需要弹出,那么我们就先用pop取出并且弹出,之后在放进去(push)就好了
int peek() {
int res = this->pop(); // 直接使用已有的pop函数
stOut.push(res); // 因为pop函数弹出了元素res,所以再添加回去
return res;
}
bool empty() {
return stIn.empty() && stOut.empty();//都没有了就是仓库没有了才说明队列没有元素
}
};
JAVA代码如下
class MyQueue {
//用到两个栈
private Stack<Integer> in;// 输入栈
private Stack<Integer> out;// 输出栈
public MyQueue() {
in = new Stack<>();
out = new Stack<>();
}
public void push(int x) {
//入栈弹入元素
in.push(x);
}
public int pop() {
// 先判断是不是有数据 ,不要直接往里放。
if(out.isEmpty()){
// 只有当out栈为空的时候,再从in栈里导入数据(导入in栈的全部数据)
//这里其实还可以更加深入的去思考一下,就是为什么一定要out栈为空的时候我们才可以添加
//因为栈是先进先出,转换出的队列也要先进先出,但是你一旦把in栈的元素放到out栈中,新放入的元素就会更快的出来,就改变了顺序。
while(!in.isEmpty()){//这就是in栈导入到out栈数据中
out.push(in.pop());
}
}
return out.pop();
}
public int peek() {//其实本方法可以不那么麻烦的列出来完整的代码,可以直接运用pop方法,就像上面C++代码一样
if(out.isEmpty()){
while(!in.isEmpty()){
out.push(in.pop());
}
}
return out.peek();
}
public boolean empty() {
return in.isEmpty() && out.isEmpty();
}
}
二、 LeetCode:225. 用队列实现栈
题目解析:其实也可以向上一道题目一样使用两次队列来模拟栈也可以,但是这里有更好的方法,只用一个队列就好。我们只需要先把元素取出来,然后再重新加入队列里,直到即将弹出最后一个元素,那么第二次这个操作就是即将弹出倒数第二个元素,以此类推,说起来复杂,其实就是这个操作每次都进行(suze - 1 )次就好了。
C++代码如下(用两个队列的方法)
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. */
int top() {
return que1.back();
}
/** Returns whether the stack is empty. */
bool empty() {
return que1.empty();
}
};
C++代码如下(一个队列的方法)
class MyStack {
public:
queue<int> que;
/** Initialize your data structure here. */
MyStack() {
}
//加入元素
void push(int x) {
que.push(x);
}
//弹出头部元素并且记录元素。
int pop() {
int size = que.size();
size--;//最大下标应该减一。
while (size--) { // 将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部
que.push(que.front());//弹出后重新放回来。A.push(B..front)把B的元素弹到A里面
que.pop();
}
int result = que.front(); // 此时弹出的元素顺序就是栈的顺序了
que.pop();
return result;
}
//只需要获取头部元素
int top() {
return que.back();
}
//判断栈是否为空,一个1队列为空就好。
bool empty() {
return que.empty();
}
};
JAVA代码如下(一个队列实现)
class MyStack {
// Deque 接口继承了 Queue 接口
// 所以 Queue 中的 add、poll、peek等效于 Deque 中的 addLast、pollFirst、peekFirst
Deque<Integer> que1;
/** Initialize your data structure here. */
public MyStack() {
que1 = new ArrayDeque<>();
}
//push方法
public void push(int x) {
que1.addLast(x);
}
//弹出并且获取头部元素
public int pop() {
int size = que1.size();
size--;//只需要进行size-1次操作
// 将 que1 导入 que2 ,但留下最后一个值
while (size-- > 0) {
que1.addLast(que1.peekFirst());
que1.pollFirst();
}
int res = que1.pollFirst();
return res;//返回值
}
//只需要获得,我们直接用函数就好
public int top() {
return que1.peekLast();
}
//是否为空,只需要队列为空。
public boolean empty() {
return que1.isEmpty();
}
}
JAVA代码如下(两个队列):
class MyStack {
// Deque 接口继承了 Queue 接口
// 所以 Queue 中的 add、poll、peek等效于 Deque 中的 addLast、pollFirst、peekFirst
Deque<Integer> que1; // 和栈中保持一样元素的队列
Deque<Integer> que2; // 辅助队列
/** Initialize your data structure here. */
public MyStack() {
que1 = new ArrayDeque<>();
que2 = new ArrayDeque<>();
}
//仅仅添加
public void push(int x) {
que1.addLast(x);
}
/** Removes the element on top of the stack and returns that element. */
public int pop() {
int size = que1.size();
size--;
// 将 que1 导入 que2 ,但留下最后一个值,注意智力也是要留下最后一个值
while (size-- > 0) {
que2.addLast(que1.peekFirst());
que1.pollFirst();
}
int res = que1.pollFirst();//弹出来第一个
// 将 que2 对象的引用赋给了 que1 ,此时 que1,que2 指向同一个队列
que1 = que2;
// 如果直接操作 que2,que1 也会受到影响,所以为 que2 分配一个新的空间
que2 = new ArrayDeque<>();
return res;
}
//获取头部。
public int top() {
return que1.peekLast();
}
/** Returns whether the stack is empty. */
public boolean empty() {
return que1.isEmpty();
}
}
总结
今天的内容其实还是蛮简单的。好好理解结构,后面的底层没有钻研,要自己钻研一下。