持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第21天,点击查看活动详情
题目描述:
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):
实现 MyQueue 类:
- void push(int x) 将元素 x 推到队列的末尾
- int pop() 从队列的开头移除并返回元素
- int peek() 返回队列开头的元素
- boolean empty() 如果队列为空,返回 true ;否则,返回 false
输入:
["MyQueue", "push", "push", "peek", "pop", "empty"]
[[], [1], [2], [], [], []]
输出: [null, null, null, 1, 1, false]
解题思路:
方法一:双栈
-
理解栈和队列
栈是一种先进后出的数据结构,栈中元素从栈顶(top)压入,也从栈顶弹出
队列是一种先进先出的数据结构,队列中的元素都从队尾(rear)入队,队首(front)出队。
-
模拟队列的行为,需要用到两个栈一个为输入栈,一个为输出栈
-
模拟队列入队(push)的时候,只要数据压入输入栈就好。模拟队列出队(pop)的时候,输出栈如果没有内容,就把输入栈全部数据依次弹出并压入(输出栈从栈顶往栈底的顺序就是队列从队首往队尾的顺序),再从栈顶弹出栈顶数据;如果输出栈存在内容,则栈顶数据直接弹出就可以了。最后如果输入栈和输出栈都为空的话,说明模拟的队列为空了。
var MyQueue = function() {
// 定义两个栈
this.inStack = [];
this.outStack = [];
};
/**
* @param {number} x
* @return {void}
*/
MyQueue.prototype.push = function(x) {
//把数据加入输入栈
this.inStack.push(x)
};
/**
* @return {number}
*/
MyQueue.prototype.pop = function() {
const size = this.outStack.length;
// 如果输出栈有数据,就直接弹出栈顶元素(相当于删除数组最后一个元素)
if(size){
return this.outStack.pop();
}
// 如果输出栈没有数据,输入栈存在数据时,将输入栈的数据一一加入输出栈中
while(this.inStack.length){
this.outStack.push(this.inStack.pop());
}
return this.outStack.pop();
};
/**
* @return {number}
*/
MyQueue.prototype.peek = function() {
const x = this.pop(); // 获得队头的数据
//因为执行了一次删除输入栈栈顶元素,所以需要把该元素加回去
this.outStack.push(x)
return x
};
/**
* @return {boolean}
*/
MyQueue.prototype.empty = function() {
return !this.inStack.length && !this.outStack.length
};
方法二: 数组、es6扩展运算符、数组的解构赋值
首先定义一个数组(模拟队列),通过数组的push()方法可以实现将元素 x 加到队列的末尾;运用es6的扩展运算符和数组的解构赋值,得到数组的第一个和后面的元素(组成一个数组newArr),在队列的pop()方法中返回数组的第一个元素,并更新数组为newArr(没有了数组的第一个元素,相当于删除了)
var MyQueue = function() {
//定义一个数组
this.arr = [];
};
MyQueue.prototype.push = function(x) {
this.arr.push(x); //在数组末尾加入元素
};
MyQueue.prototype.pop = function() {
let [a, ...newArr] = this.arr;
this.arr = newArr;
return a;
};
MyQueue.prototype.peek = function() {
return this.arr[0]; //返回数组第一个元素
};
MyQueue.prototype.empty = function() {
return !this.arr.length;
};