两个栈实现队列|刷题打卡

97 阅读1分钟

掘金团队号上线,助你 Offer 临门! 点击 查看详情

一、题目描述

用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )

示例:

输入

["CQueue","appendTail","deleteHead","deleteHead"]
[[],[3],[],[]]

输出

[null,null,3,-1]

限制

1 <= values <= 10000
最多会对 appendTail、deleteHead 进行 10000 次调用

二、思路分析

我的思路

  1. 先使用一个队列专门用来append的。
  2. 当需要删除的时候,就需要将最下面的一个拿出来,此时就使用另一个栈存放上面的元素,弹出后,然后再将之前的元素放回去。
  3. 这个很显然最简单的思路了。肯定可以优化。
  4. 我的做法其实,put和delete都指望在一个栈完成!另外一个栈只是用来辅助的,想的太复杂了(其实就是想得太笨了)。

最佳思路

  1. 思路大都一致:但是我的思路多了第二个循环再放回去这步骤
  2. 使用一个栈,专门用来append到来的数据。另外一个栈专门用来delete。
    • 比如主要append的栈为A,负责delete的栈为B。那么put的时候,即往栈压入A,当需要删除的时候,需要删除的元素在A的最下面,此时我们需要将上面的元素全部放入B中!
    • 这时候就很关键了:当需要继续put的时候,我们只要继续往A继续put就行了,并不需要将之前压入B的都取出来,那没有意义。
    • 然后进行删除的时候,我们从B取最上面的元素,当B没有了的时候,我们再执行一次将A全部压入B的操作
    • (其实道理也很简单,但是脑子一时没有转过这个弯)

三、AC 代码

Stack<Integer> mainStack;
Stack<Integer> backupStack;
public CQueue() {
  	// 使用2个栈构建队列
    mainStack = new Stack<>();
    backupStack = new Stack<>();
}
public void appendTail(int value) {
    // put只往main栈put
    mainStack.push(value);
}
// 我的写法
public int deleteHead() {
    if (mainStack.isEmpty()) {
        return -1;
    }
  	// 主栈不为空的话,就将main的数据先put到backup
    while (!mainStack.empty()) {
        backupStack.push(mainStack.pop());
    }
    // 然后弹出backup最上面的
    int res = backupStack.pop();
    // 然后再将元素放回去。。。。。。😓
    while (!backupStack.empty()) {
        mainStack.push(backupStack.pop());
    }
    return res;
}
// 最佳写法
public int deleteHeadGood() {
    // 删除直接从backup删除,如果backup是空的,那么就将main当前所有的元素都压入到backup中
    if (backupStack.isEmpty()) {
        if (mainStack.isEmpty()) {
            return -1;
        }
        while (!mainStack.isEmpty()) {
            backupStack.push(mainStack.pop());
        }
    }
    return backupStack.pop();
}

四、总结

核心点:记住2个栈,让一个栈负责接收put,另外一个栈负责delete