232. 用栈实现队列

232. 用栈实现队列

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(双端队列)来模拟一个栈,只要是标准的栈操作即可。

示例 1:

输入:
["MyQueue", "push", "push", "peek", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 1, 1, false]

解释:
MyQueue myQueue = new MyQueue();
myQueue.push(1); // queue is: [1]
myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)
myQueue.peek(); // return 1
myQueue.pop(); // return 1, queue is [2]
myQueue.empty(); // return false
 

提示:

  • 1 <= x <= 9
  • 最多调用 100 次 push、pop、peek 和 empty
  • 假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)

进阶:

你能否实现每个操作均摊时间复杂度为 O ( 1 ) O(1) O(1) 的队列?换句话说,执行 n n n 个操作的总时间复杂度为 O ( n ) O(n) O(n) ,即使其中一个操作可能花费较长时间。

思路:
题目都已经告知是需要两个栈,那么这两个栈都应该设置成队列的成员属性,一个栈用于实际存放元素,而另一个栈就是用于各种操作时的中间容器而已。

解法一
元素永远保存在stack1(主栈中),stack2(辅助栈)只是作为一个中间容器。
在这里插入图片描述
显然,这里只需要进队和出队操作,所以每次移到stack2的数据是可以不用移回来了的。详见解法二。

解法二

stack1仍然是主栈,插入操作直接进stack1即可,而出队操作时,可以先判断stack2是否是空的,非空则直接出栈一个元素即是队列的对头元素,若是stack2空,则将stack1的元素都移到stack2,刚好又逆序,符合出队的顺序了。

Go代码

type MyQueue struct {
    // 主栈,用于入栈操作
    MainStack []int
    // 辅助栈,用于查看和出栈操作
    HelpStack []int
}


func Constructor() MyQueue {
    return MyQueue{
        MainStack : make([]int,0),
        HelpStack : make([]int,0),
    }
}


func (this *MyQueue) Push(x int)  {
    this.MainStack  = append(this.MainStack,x)
}


func (this *MyQueue) Pop() int {
    // 辅助栈中没有元素的时候,将主栈元素全部移入辅助栈
    if len(this.HelpStack) == 0 {
        this.mainStackToHelpStack()   
    }
    
    // 移完后还是空,说明整个队列都空了,无法pop
    if len(this.HelpStack) == 0 {
        return -1
    }
    
    // pop
    res := this.HelpStack[len(this.HelpStack)-1]
    this.HelpStack = this.HelpStack[0:len(this.HelpStack)-1]
    return res
}


func (this *MyQueue) Peek() int {
    // 辅助栈中没有元素的时候,将主栈元素全部移入辅助栈
    if len(this.HelpStack) == 0 {
        this.mainStackToHelpStack()   
    }
    
    // 移完后还是空,说明整个队列都空了,无法pop
    if len(this.HelpStack) == 0 {
        return -1
    }
    
    // peek
    return this.HelpStack[len(this.HelpStack)-1]
}


func (this *MyQueue) Empty() bool {
    fmt.Println(len(this.MainStack),len(this.HelpStack))
    return len(this.MainStack) == 0 && len(this.HelpStack) == 0
}

// 将主栈元素全部移入辅助栈
func(this *MyQueue) mainStackToHelpStack() {
    // 从后往前取数即可认为是出栈操作
    for i := len(this.MainStack) - 1;i >= 0;i--{
        this.HelpStack = append(this.HelpStack,this.MainStack[i])
    }
    // 移动完成后,清空MainStack
    this.MainStack = make([]int,0)
}


/**
 * Your MyQueue object will be instantiated and called as such:
 * obj := Constructor();
 * obj.Push(x);
 * param_2 := obj.Pop();
 * param_3 := obj.Peek();
 * param_4 := obj.Empty();
 */

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值