9. 用兩個棧實現隊列(劍指 Offer 題解Java版)

2020-12-25 酷扯兒

本文轉載自【微信公眾號:五角錢的程式設計師,ID:xianglin965】經微信公眾號授權轉載,如需轉載與原文作者聯繫

文章目錄

9. 用兩個棧實現隊列題目連結題目描述解題思路分析Java實現棧Java實現隊列用兩個棧實現隊列

9. 用兩個棧實現隊列

題目連結

牛客網

https://www.nowcoder.com/practice/54275ddae22f475981afa2244dd448c6?tpId=13&tqId=11158&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking&from=cyc_github

題目描述

用兩個棧來實現一個隊列,完成隊列的 Push 和 Pop 操作。

解題思路

in棧用來處理入棧(push)操作,out棧用來處理出棧(pop)操作。一個元素進入in棧之後,出棧的順序被反轉。當元素要出棧時,需要先進入out棧,此時元素出棧順序再一次被反轉,因此出棧順序就和最開始入棧順序是相同的,先進入的元素先退出,這就是隊列的順序。

分析

棧的特點是先進後出,而隊列的特點是先進先出,主要就是在兩個棧中來回倒騰從而實現隊列的功能,就好像一個黑盒子,裡邊是兩個棧的操作,但其他人在用這個黑盒子的時候,感覺就像在用隊列一樣。隊列和棧只是邏輯性的數據結構,實現隊列和棧可以用數組實現,也可以用鍊表實現,只要滿足隊列先進先出,棧先進後出的特性就可以。

用兩個棧實現隊列,比如一開始在stack1中把a,b,c入棧,想刪除虛擬隊列的隊首元素時,即刪除a,但是a在棧底,無法直接刪除,所以這個時候就要利用stack2了,在進行刪除操作時,可以把stack1中的c,b,a依次彈出併入棧到stack2中,此時a就在stack2的棧頂了,可以直接pop掉。現在b變成stack2的棧頂元素了,繼續刪除b,直接就可以pop,這就完成了隊列的pop操作。那麼怎麼插入一個新元素呢,比如插入d,那麼可以讓d直接入棧到stack1。繼續刪除隊列隊首元素,從stack2中刪除c,然後把d彈出stack1併入棧stack2,然後從stack2中直接pop。通過觀察我們發現,如果進行虛擬隊列的push操作,可以把元素直接入棧到stack1;如果進行虛擬隊列的pop操作,如果stack2為空,那麼把stack1中所有的元素彈出併入棧到stack2,然後對stack2進行pop操作;如果stack2不為空,那麼直接對stack2進行pop操作,到這裡你是不是已經思路變得清晰了。

我們先來用Java的LinkedList鍊表數據結構來實現鏈式棧和鏈式隊列,為後面的用兩個棧實現隊列和用兩個隊列實現棧來服務。

Java實現棧

package 用兩個棧實現隊列;/*

作者 :XiangLin

文件 :stackDemo.java

IDE :IntelliJ IDEA

*/

import java.util.Iterator;

import java.util.LinkedList;

/**

* 棧

*/

public class stackDemo {

private LinkedList<String> stackList = new LinkedList<>();

/**

* 入棧

*/

public void push(String str){

stackList.addFirst(str);

}

/**

*

*/

public String pop(){

return stackList.removeFirst();

}

/**

* 判斷是否為空

*/

public boolean empty(){

return stackList.isEmpty();

}

/**

* 列印棧內所有元素

*/

public void printStack(){

Iterator iterator = stackList.iterator();

while (iterator.hasNext()){

System.out.println(iterator.next() + " ");

}

System.out.println();

}

public static void main(String[] args) {

stackDemo stack = new stackDemo();

System.out.println(stack.empty());

stack.printStack();

stack.push("a");

stack.push("b");

stack.push("c");

System.out.println(stack.empty());

stack.printStack();

}

}

輸出:

true

false

c

b

a

Java實現隊列

package 用兩個棧實現隊列;/*

作者 :XiangLin

文件 :QueueDemo.java

IDE :IntelliJ IDEA

*/

import java.util.Iterator;

import java.util.LinkedList;

/**

* 隊列

*/

public class QueueDemo {

private LinkedList<String> queueList = new LinkedList<String>();

/**

* 入隊列

*/

public void push(String str){

queueList.add(str);

}

/**

* 出隊列

*/

public String pop(){

return queueList.removeFirst();

}

/**

* 獲得隊列元素個數

*/

public int getQueueSize(){

return queueList.size();

}

/**

* 判斷隊列是否為空

*/

public boolean empty(){

return queueList.isEmpty();

}

/**

* 列印隊列內所有元素

*/

public void printQueue(){

Iterator iterator = queueList.iterator();

while(iterator.hasNext()) {

System.out.println(iterator.next()+" ");

}

System.out.println();

}

public static void main(String[] args) {

QueueDemo queueDemo = new QueueDemo();

queueDemo.push("a");

queueDemo.push("b");

queueDemo.push("c");

System.out.println(queueDemo.queueList.size());

queueDemo.pop();

queueDemo.printQueue();

System.out.println(queueDemo.queueList.size());

}

}

輸出:

3

b

c

2

用兩個棧實現隊列

package 用兩個棧實現隊列;/*

作者 :XiangLin

文件 :TwoStackToQueue.java

IDE :IntelliJ IDEA

*/

/**

* 用兩個棧實現隊列

*/

public class TwoStackToQueue {

stackDemo stack1 = new stackDemo();

stackDemo stack2 = new stackDemo();

/**

* 入隊列

*/

public void push(String str){

stack1.push(str);

}

/**

* 出隊列

*/

public String pop(){

if (stack2.empty()){

// 如果棧2為空,就要把棧1所有元素反彈到棧2中

while (!stack1.empty()){

stack2.push(stack1.pop());

}

}

return stack2.pop();

}

/**

* 判斷新隊列是否為空

*/

public boolean empty(){

if(stack1.empty() && stack2.empty()){

return true;

}else {

return false;

}

}

/**

* 列印隊列中所有元素

*/

public void printQueue(){

System.out.println("棧1中:");

stack1.printStack();

System.out.println("棧2中:");

stack2.printStack();

}

public static void main(String[] args) {

TwoStackToQueue queue = new TwoStackToQueue();

queue.push("a");

queue.push("b");

queue.push("c");

queue.printQueue();

queue.pop();

queue.printQueue();

}

}

輸出:

棧1中:

c

b

a

棧2中:

棧1中:

棧2中:

b

c

相關焦點

  • 劍指 Offer 55 - II. 平衡二叉樹 - leetcode 劍指offer系列
    題目難度: 簡單原題連結[1]今天繼續更新劍指 offer 系列, 老樣子晚上 6 點 45 分準時更新公眾號 每日精選算法題, 大家記得關注哦~ 另外在公眾號裡回復 offer 就能看到劍指 offer 系列當前連載的所有文章了題目描述輸入一棵二叉樹的根節點,判斷該樹是不是平衡二叉樹。
  • 18.1在 O(1) 時間內刪除鍊表節點(劍指 Offer 題解Java版)
    測試用例功能測試(多個結點鍊表,刪除頭結點、中間結點和尾結點;單個結點鍊表)特殊測試(頭結點或刪除結點為null)package 劍指offer.在O時間內刪除鍊表節點;/*作者 :XiangLin
  • 劍指offer python實現 66道算法題
    github地址:https://github.com/leeguandong/Interview-code-practice-python/tree/master/%E5%89%91%E6%8C%87offer數組
  • Java實現簡單延遲隊列和分布式延遲隊列
    在我們的工作中,很多地方使用延遲隊列,比如訂單到期沒有付款取消訂單,制訂一個提醒的任務等都需要延遲隊列,那麼我們需要實現延遲隊列。我們本文的梗概如下,同學們可以選擇性閱讀。1. 實現一個簡單的延遲隊列。
  • 10.2 矩形覆蓋(劍指 Offer 題解Java版)
    如需轉載與原文作者聯繫文章目錄10.2 矩形覆蓋題目描述題目連結關於分治法代碼實現10.2 矩形覆蓋題目描述我們可以用2*1的小矩形橫著或者豎著去覆蓋更大的矩形。請問用n個2*1的小矩形無重疊地覆蓋一個2*n的大矩形,總共有多少種方法?題目連結NowCoder關於分治法分治法,分而治之。就是將原問題劃分為n個規模較小,結構與原問題類似的小問題進行處理,遞歸地解決這些問題,然後再合併求解的過程。
  • 劍指 Offer 58 - I. 翻轉單詞順序 - leetcode 劍指offer系列
    題目難度: 簡單原題連結[1]今天繼續更新劍指 offer 系列, 老樣子晚上 6 點 45 分準時更新公眾號 每日精選算法題, 大家記得關注哦~ 另外在公眾號裡回復 offer 就能看到劍指 offer 系列當前連載的所有文章了題目描述輸入一個英文句子,翻轉句子中單詞的順序,但單詞內字符的順序不變。
  • 矩陣中的路徑(劍指 Offer 題解Java版)
    矩陣中的路徑題目描述題目連結解題思路實現代碼12實現代碼package 矩陣中的路徑;/*作者 :XiangLin文件 :StringPathInMatrix.javaIDE :IntelliJ IDEA
  • 數值的整數次方(劍指 Offer 題解Java版)
    數值的整數次方題目連結題目描述解題思路實現代碼16. 數值的整數次方題目連結NowCoder題目描述給定一個 double 類型的浮點數 base 和 int 類型的整數 exponent,求 base 的 exponent 次方。解題思路下面的討論中 x 代表 base,n 代表 exponent。
  • 二叉樹的下一個結點(劍指 Offer 題解Java版)
    二叉樹的下一個結點題目連結題目描述解題思路代碼實現代碼實現package 二叉樹的下一個結點;/*作者 :XiangLin文件 :GetNext.javaIDE :IntelliJ IDEA
  • 二進位中 1 的個數(劍指 Offer 題解Java版)
    NowCoder題目描述任意給定一個32位無符號整數n,求n的二進位表示中1的個數,比如n = 5(0101)時,返回2,n = 15(1111)時,返回4這也是一道比較經典的題目了,相信不少人面試的時候可能遇到過這道題吧,下面介紹了幾種方法來實現這道題
  • JS 數據結構與算法——棧 & 隊列
    始終保持兩個棧中的元素個數相同,壓棧時判別壓入的元素與 minStack棧頂元素比較大小,如果比棧頂元素小,則直接入棧,否則複製棧頂元素入棧;彈出棧頂時,兩者均彈出即可。這樣 minStack的棧頂元素始終為最小值。classMinStack{ constructor(){this._dataStack =newStack();this.
  • 替換空格(劍指 Offer 題解Java版)
  • java中的Queue隊列的用法
    大家好,歡迎來到雄雄的小課堂,今天給大家分享的是「java中的Queue隊列的用法」 前言:好多人對Queue不是很熟悉,畢竟平時也不怎麼用,遇到集合要麼List要麼map這些常用的,殊不知,java中還有個Queue,今天,我們就來看看Queue的用法。
  • 阻塞隊列實現生產者消費者以及同步工具類
    阻塞隊列阻塞隊列提供可阻塞的put和take方法,支持定時的offer和poll方法,如果隊列已經滿了,那麼put方法將阻塞直到有空間可用;如果隊列為空,那麼take方法將會阻塞直到有元素可用;同時隊列可以是有界也可以是無界的,無界隊列永遠都不會充滿,因此無界隊列的put方法永遠不會阻塞;
  • 10.1 斐波那契數列(劍指 Offer 題解Java版)
  • Java中常用隊列的總結
    隊列是一種先進先出(FIFO)的抽象數據結構,在Java中,隊列使用了兩種數據類型來實現的,分別是:數組和鍊表這兩種數據結構。本文主要內容:回顧Java中常用的七個阻塞隊列進行總結及阻塞隊列中四組AP並進行總結。本文來源:本文是由凱哥Java(kaigejava)原創發布。
  • 面試官:你手寫過堵塞隊列嗎?
    某人:沒有手寫過。因為生產者的生產速度和消費者的消費速度之間的不匹配,就可以通過堵塞隊列讓速度快的暫時堵塞,如生產者每秒生產兩個數據,而消費者每秒消費一個數據,當隊列已滿時,生產者就會堵塞(掛起),等待消費者消費後,再進行喚醒。堵塞隊列會通過掛起的方式來實現生產者和消費者之間的平衡,這是和普通隊列最大的區別。3.如何實現堵塞隊列?
  • 刷題兩個月,從入門到字節跳動offer,這是我的模板|GitHub1.2k星
    題目也是常見的高頻題,很有代表性,大部分都是可以用模版加一點變形做出來的。這樣刷完了之後就會對大部分題目有個最基本的認識。第二步,LeetCode探索卡片接著,就可以去刷LeetCode的探索卡片了。第三步,劍指offer劍指offer基本上是大部分公司的出題源頭,刷題面試中基本會遇到現題或者變形題,刷完這三部分,大部分國內公司的面試題應該都沒有問題了。另外,作者還溫馨提示:刷題時間要合理分配。
  • 調整數組順序使奇數位於偶數前面(劍指 Offer 題解,面試)
    package 劍指offer.調整數組順序使奇數位於偶數前面_21;/*作者 :XiangLin文件 :OrderArray.javaIDE :IntelliJ IDEA*/import java.util.Arrays;public class OrderArray {
  • 旋轉數組的最小數字(劍指 Offer 題解Java版)