• 剑指 Offer 09. 用两个栈实现队列


    剑指 Offer 09. 用两个栈实现队列

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

    示例 1:

    输入:
    ["CQueue","appendTail","deleteHead","deleteHead"]
    [[],[3],[],[]]
    输出:[null,null,3,-1]

    示例 2:

    输入:
    ["CQueue","deleteHead","appendTail","appendTail","deleteHead","deleteHead"]
    [[],[],[5],[2],[],[]]
    输出:[null,-1,null,null,5,2]

    提示:

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

    解法一:

    stack1用存数据,stack2用来辅助取数据,取数据时,如果stack1为空,直接返回-1,否则先把所有元素压入到stack2中,弹出并记录stack2栈顶元素,把stack2所有元素再压回到stack1

     1 class CQueue {
     2 
     3     Stack<Integer> stack1;
     4     Stack<Integer> stack2;
     5 
     6     public CQueue() {
     7         stack1 = new Stack<Integer>();
     8         stack2 = new Stack<Integer>();
     9     }
    10     
    11     public void appendTail(int value) {
    12         stack1.push(value);
    13     }
    14     
    15     public int deleteHead() {
    16         // 如果stack1为空,直接返回-1
    17         if(stack1.isEmpty()){
    18             return -1;
    19         }else{
    20             // 否则先把所有元素压入到stack2中
    21             while(!stack1.isEmpty()){
    22                 stack2.push(stack1.pop());
    23             }
    24             // 弹出并记录栈顶元素
    25             int top = stack2.pop();
    26 
    27             // 把stack2所有元素再压回到stack1
    28             while(!stack2.isEmpty()){
    29                 stack1.push(stack2.pop());
    30             }
    31             return top;
    32         }
    33     }
    34 }

    leetcode运行时间为332ms, 空间为46.7mb, 这个时间太恐怖了

    复杂度分析:

    时间复杂度:插入元素的复杂度为O(1), 删除元素的复杂度为O(2n)

    空间复杂度:两个栈, 所以为O(2n)

    解法二:

    思路来源:https://leetcode-cn.com/problems/yong-liang-ge-zhan-shi-xian-dui-lie-lcof/solution/mian-shi-ti-09-yong-liang-ge-zhan-shi-xian-dui-l-3/597550

    两个栈,一个用来存,一个用来取,两个栈的元素之和等于当前所有元素。stack2不是取元素的辅助栈,而是专门用来取元素,取元素时,先判断 stack2是否为空,如果为空,把stack1中的所有元素都搬运到stack2,此时stack2的栈顶到栈底的元素排列顺序就是将来取元素的顺序

     1 class CQueue {
     2 
     3     Stack<Integer> stack1;
     4     Stack<Integer> stack2;
     5 
     6     public CQueue() {
     7         stack1 = new Stack<Integer>();
     8         stack2 = new Stack<Integer>();
     9     }
    10     
    11     public void appendTail(int value) {
    12         stack1.push(value);
    13     }
    14     
    15     public int deleteHead() {
    16         if(stack2.isEmpty()){
    17             while(!stack1.isEmpty()){
    18                 stack2.push(stack1.pop());
    19             }
    20         }
    21         if(stack2.isEmpty()){
    22             return -1;
    23         }else{
    24             // 如果不为空,直接返回stack2的栈顶元素
    25             return stack2.pop();
    26         }
    27     }
    28 }

    leetcode运行时间为55ms, 空间为46.5mb, 这个时间已经好多了

    复杂度分析:

    时间复杂度:存元素的时间为O(1), 取元素虽然有时需要把stack1 的所有元素都拷贝到 stack2, 但是每个元素只会入栈和出栈 stack2 一次,所以取元素的平均时间也为O(1)

    空间复杂度:两个栈,一个用来存,一个用来取,两个栈的元素之和等于当前所有元素,所以空间复杂度为O(n)

  • 相关阅读:
    36_Cache Aside Pattern缓存+数据库读写模式的分析
    35_亿级流量商品详情页的多级缓存架构以及架构中每一层的意义
    34_redis阶段性总结:1T以上海量数据+10万以上QPS高并发+99.99%高可用
    33_redis在实践中的一些常见问题以及优化思路(包含linux内核参数优化)
    正则表达式全部符号解释
    如何正确学习JavaScript
    2015阿里校招前端笔试题
    前端面试总结2
    前端面试总结
    通俗易懂的来讲讲DOM
  • 原文地址:https://www.cnblogs.com/hi3254014978/p/13746141.html
Copyright © 2020-2023  润新知