代码随想录算法训练营第十天|232.用栈实现队列、225. 用队列实现栈 「栈与队列」

88 阅读4分钟

232. 用栈实现队列

题目

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(pushpoppeekempty): 实现 MyQueue 类:

  • void push(int x) 将元素 x 推到队列的末尾
  • int pop() 从队列的开头移除并返回元素
  • int peek() 返回队列开头的元素
  • boolean empty() 如果队列为空,返回 true ;否则,返回 false 说明
  • 你 只能 使用标准的栈操作 —— 也就是只有 push to toppeek/pop from topsize, 和 is empty 操作是合法的。
  • 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。

思路

一开始感觉没什么思路,每次遇到这种模拟题都有点害怕,不知道要我做什么,然后看了一下代码随想录的那个gif图片,然后就理解了,自己尝试做了一下,但是感觉自己写的非常复杂,优化空间很大,简单说一下我的思路:

  1. 首先创建队列,内部放两个栈结构,一个命名入栈,一个命名出栈,这两个栈结构都只能使用push,pop从数组尾部增删元素
  2. 增加元素,直接增加找入栈数组的尾部
  3. 删除元素,判断出栈数组中是否存在元素
    1. 如果存在就从出栈数组尾部弹出元素
    2. 如果不存在就先把入栈数组的从尾部取出然后放进出栈数组中,顺序是和入栈数组中元素的相反
  4. 查找栈顶元素,判断出栈数组中是否有元素
    1. 如果有就返回出栈元素的尾部元素
    2. 如果没有就返回入栈数组的头部元素
  5. 判断栈是否为空,如果出栈数组和入栈数组都为空就返回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)的栈,并支持普通栈的全部四种操作(pushtoppop 和 empty)。 实现 MyStack 类:

  • void push(int x) 将元素 x 压入栈顶。
  • int pop() 移除并返回栈顶元素。
  • int top() 返回栈顶元素。
  • boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。 注意
  • 你只能使用队列的基本操作 —— 也就是 push to backpeek/pop from frontsize 和 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总结

今天的题不是很难,不是算法,是一些模拟题,对理解队列和栈的结构有很大的帮助。