232. 用栈实现队列
题目:
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):
实现 MyQueue 类:
void push(int x)将元素 x 推到队列的末尾int pop()从队列的开头移除并返回元素int peek()返回队列开头的元素boolean empty()如果队列为空,返回true;否则,返回false说明:- 你 只能 使用标准的栈操作 —— 也就是只有
push to top,peek/pop from top,size, 和is empty操作是合法的。 - 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
思路:
一开始感觉没什么思路,每次遇到这种模拟题都有点害怕,不知道要我做什么,然后看了一下代码随想录的那个gif图片,然后就理解了,自己尝试做了一下,但是感觉自己写的非常复杂,优化空间很大,简单说一下我的思路:
- 首先创建队列,内部放两个栈结构,一个命名入栈,一个命名出栈,这两个栈结构都只能使用push,pop从数组尾部增删元素
- 增加元素,直接增加找入栈数组的尾部
- 删除元素,判断出栈数组中是否存在元素
- 如果存在就从出栈数组尾部弹出元素
- 如果不存在就先把入栈数组的从尾部取出然后放进出栈数组中,顺序是和入栈数组中元素的相反
- 查找栈顶元素,判断出栈数组中是否有元素
- 如果有就返回出栈元素的尾部元素
- 如果没有就返回入栈数组的头部元素
- 判断栈是否为空,如果出栈数组和入栈数组都为空就返回true,否则返回false
写完以后感觉自己也许有些逻辑比较复杂
代码:
var MyQueue = function() {
this.inStack = []
this.outStack = []
};
/**
* @param {number} x
* @return {void}
*/
MyQueue.prototype.push = function(x) {
this.inStack.push(x)
console.log('push',this.inStack)
};
/**
* @return {number}
*/
MyQueue.prototype.pop = function() {
if (this.outStack.length){
return this.outStack.pop()
}else {
let len = this.inStack.length
for (let i = 0; i<len;i++) {
this.outStack.push(this.inStack.pop())
}
console.log(this.outStack)
return this.outStack.pop()
}
};
/**
* @return {number}
*/
MyQueue.prototype.peek = function() {
if (this.outStack.length) {
return this.outStack[this.outStack.length-1]
}else {
return this.inStack[0]
}
};
/**
* @return {boolean}
*/
MyQueue.prototype.empty = function() {
console.log(this.inStack)
console.log(this.outStack)
return !this.inStack.length&&!this.outStack.length?true:false
return boolean
};
优化:
看了一下大佬的代码和我的差不多,有一点不一样,就是在查找栈顶元素的时候,他没有做判断,而是直接把入栈数组的尾元素取出放出出栈数组中,然后再把这个元素输出一下,某种程度上,确实是一种简化操作。
代码:
// 使用两个数组的栈方法(push, pop) 实现队列
/**
* Initialize your data structure here.
*/
var MyQueue = function() {
this.stackIn = [];
this.stackOut = [];
};
/**
* Push element x to the back of queue.
* @param {number} x
* @return {void}
*/
MyQueue.prototype.push = function(x) {
this.stackIn.push(x);
};
/**
* Removes the element from in front of queue and returns that element.
* @return {number}
*/
MyQueue.prototype.pop = function() {
const size = this.stackOut.length;
if(size) {
return this.stackOut.pop();
}
while(this.stackIn.length) {
this.stackOut.push(this.stackIn.pop());
}
return this.stackOut.pop();
};
/**
* Get the front element.
* @return {number}
*/
MyQueue.prototype.peek = function() {
const x = this.pop();
this.stackOut.push(x);
return x;
};
/**
* Returns whether the queue is empty.
* @return {boolean}
*/
MyQueue.prototype.empty = function() {
return !this.stackIn.length && !this.stackOut.length
};
总结:
其实对于栈和队列,平时学习中接触的还是比较多的,自己也比较熟悉,用栈去实现队列其实也不难,只要想通那一点就能做出来。
225. 用队列实现栈
题目:
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。
实现 MyStack 类:
void push(int x)将元素 x 压入栈顶。int pop()移除并返回栈顶元素。int top()返回栈顶元素。boolean empty()如果栈是空的,返回true;否则,返回false。 注意:- 你只能使用队列的基本操作 —— 也就是
push to back、peek/pop from front、size和is empty这些操作。 - 你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
思路:
用两个队列好实现,一个队列在pop哪里想不到思路。
代码:
没写.
优化:
看了一下一个队列实现的思路,我一直在想是不是可以用一个方法,把队列中前部的元素取出来备份,然后把末尾的元素弹出后,再把备份的放回去,我怎么就没想到队列是头尾相接,我很蠢。 思路就是把队列前部的元素按顺序取出添加到队列末尾,然后判断如果当前操作顺序等于队列长度减一,说明此时队列开头的元素就是栈顶的元素,直接弹出。当然要添加一个判断条件,如果当前队列只有一个元素,那直接弹出这个元素就可以了。
代码:
var MyStack = function() {
this.queue = []
};
/**
* @param {number} x
* @return {void}
*/
MyStack.prototype.push = function(x) {
this.queue.push(x)
};
/**
* @return {number}
*/
MyStack.prototype.pop = function() {
if (this.queue.length===1) return this.queue.shift()
for (let i = 1;i<=this.queue.length;i++) {
this.queue.push(this.queue.shift())
if (i === this.queue.length-1) {
return this.queue.shift()
}
}
};
/**
* @return {number}
*/
MyStack.prototype.top = function() {
return this.queue[this.queue.length-1]
};
/**
* @return {boolean}
*/
MyStack.prototype.empty = function() {
return !this.queue.length?true:false
};
总结:
学习到了这种灵活运用队列和栈的特性相互转换的思路。
Day总结
今天的题不是很难,不是算法,是一些模拟题,对理解队列和栈的结构有很大的帮助。