剑指 Offer 每日一题 | 6、用两个栈实现队列

剑指 Offer 每日一题 | 6、用两个栈实现队列

这是我参与8月更文挑战的第3天,活动详情查看:8月更文挑战

一、前言

大家好,本文章属于《剑指 Offer 每日一题》中的系列文章中的第 6 篇。

在该系列文章中我将通过刷题练手的方式来回顾一下数据结构与算法基础,同时也会通过博客的形式来分享自己的刷题历程。如果你刚好也有刷算法题的打算,可以互相鼓励学习。我的算法基础薄弱,希望通过这两三个月内的时间弥补这块的漏洞。本次使用的刷题语言为 Java ,预计后期刷第二遍的时候,会采用 Python 来完成。

二、题目

用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 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]
 ​
复制代码

三、解题

这题属实有点难以理解这个示例的样子,可能是解题经验不够老道吧。在查看之后,原来是这样的意思。

这三行的意思:

 代码执行的操作方法:
 ["CQueue","appendTail","deleteHead","deleteHead"]
 传入方法的参数:
 [[],[3],[],[]]
 执行的返回值:
 输出:[null,null,3,-1]
复制代码

两个栈实现一个队列,思路是很好理解。栈的特性是先进后出,从一个栈进入再到另一个栈出来即可完成这种效果,对应代码应该如何实现呢?

3.1 思路

我们可以依据题意,构造两个栈 stack1 和 stack2 。 同时也有两个方法:appendTail(插入) 和 deleteHead(弹出)栈尾元素。

java 中有个 stack 类,通过它可以调用弹出和插入元素的方法。

插入比较简单,直接向stack1 中插入即可。

而删除元素需要考虑几种情况:

  • 情况1:此时stack1 中没有元素,stack2 中没有元素,此时返回 -1
  • 情况2:栈1 中有元素,栈2 中没有元素,则把栈1 的元素搬运到栈2中,然后在栈2 中弹出
  • 情况3:栈1有元素或没有元素,栈2 中有元素,直接从栈2中弹出,不管栈1

3.2 代码

 public class StackQueue {
 ​
     public static class CQueue{
         Stack<Integer> stack1 =new Stack<Integer>();
         Stack<Integer> stack2 = new Stack<Integer>();
         public CQueue(){}
         // 将新增的元素存在stack1
         void  appendTail(int value){
             stack1.push(value);
         }
         // 删除元素:先把stack1 元素移入stack2 ,在从statck2 中删除
         int deleteHead(){
             if(!stack2.empty()){
                 return stack2.pop();
             }else{
                 if(stack1.empty()){
                     return -1;
                 }
                 while (!stack1.empty()){
                     stack2.push(stack1.pop());
                 }
                 return stack2.pop();
             }
         }
     }
 ​
     public static void main(String[] args) {
 ​
         CQueue cQueue = new CQueue();
         cQueue.appendTail(1);
         cQueue.appendTail(2);
         cQueue.appendTail(3);
         System.out.println(cQueue.deleteHead());
         System.out.println(cQueue.deleteHead());
         System.out.println(cQueue.deleteHead());
     }
 }
复制代码

3.3 执行效果

本次的执行效率非常高。超过了90%的 java 代码。

image-20210803210101486

3.4 复杂度分析

  • 时间复杂度:append 函数为 O(1),delete 函数为O(N)
  • 空间复杂度:O(N),最坏情况下栈1中存满元素。

四、总结

本题初看可能理解不能理解题目的意思,但经过分析之后,我们可以明白这三行示例代码的含义,这也许就是出题的行规吧,

本题考察了对栈和队列的理解。通过几行代码,可以把这个场景模拟出来。

今天的刷题就到这了,欢迎点赞评论交流,剑指 Offer 刷题之旅将继续展开!

分类:
后端
标签: