日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

队列实现栈的3种方法,全都击败了100%的用户!

發(fā)布時間:2025/3/11 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 队列实现栈的3种方法,全都击败了100%的用户! 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

作者 | 王磊

來源 | Java中文社群(ID:javacn666)

轉(zhuǎn)載請聯(lián)系授權(quán)(微信ID:GG_Stone)

本文已收錄至 Github《小白學算法》系列:https://github.com/vipstone/algorith

之前我們講過《用兩個棧實現(xiàn)一個隊列》,而今天我們要講的是「用隊列實現(xiàn)棧」,它們都屬于常見的面試題,而我們今天要用多種方法來實現(xiàn)隊列到棧的“轉(zhuǎn)變”。

老規(guī)矩,先來回顧一下棧(Stack)和隊列(Queue)的特性和常見方法。

棧是后進先出(LIFO)的數(shù)據(jù)結(jié)構(gòu),常見方法如下:

  • push():入棧方法,向棧頂添加元素;

  • pop():出棧方法,將棧頂?shù)脑匾瞥⒎祷卦?#xff1b;

  • peek():查詢棧頂元素,并不會移除元素。

隊列是先進先出(FIFO)的數(shù)據(jù)結(jié)構(gòu),常見方法如下:

  • offer():入隊方法,向隊尾添加元素;

  • poll():出隊方法,從隊頭移除并返回元素;

  • peek():查詢隊頭元素,并不會移除元素。

知道了這些基礎內(nèi)容之后,就來看今天的問題吧。

題目描述

使用隊列實現(xiàn)棧的下列操作:

push(x) -- 元素 x 入棧

pop() -- 移除棧頂元素

top() -- 獲取棧頂元素

empty() -- 返回棧是否為空

注意:

  • 你只能使用隊列的基本操作-- 也就是 push to back, peek/pop from front, size, 和 is empty 這些操作是合法的;

  • 你所使用的語言也許不支持隊列。你可以使用 list 或者 deque(雙端隊列)來模擬一個隊列 , 只要是標準的隊列操作即可;

  • 你可以假設所有操作都是有效的(例如, 對一個空的棧不會調(diào)用 pop 或者 top 操作)。

LeetCode 225:https://leetcode-cn.com/problems/implement-stack-using-queues/

題目解析

這道題的題目很好理解:只需要將先進先出的隊列,轉(zhuǎn)換為后進先出的“棧”就可以了,我們可以從多個方向入手來實現(xiàn)此功能,比如使用兩個隊列插入并交換的方式,或者是一個隊列插入再交換的方式,或雙端隊列的方式來實現(xiàn)此功能,具體實現(xiàn)方法和代碼如下。

實現(xiàn)方法 1:兩個隊列實現(xiàn)棧

之前我們用兩個棧實現(xiàn)了一個隊列的文章中,主要使用的是「負負得正」的思想,那么當看到此道題時,首先應該想到的是用兩個隊列來實現(xiàn)一個棧,但這里的實現(xiàn)思路和用棧實現(xiàn)隊列的思路又略有不同,因為隊列都是先進先出的,我們可以把它理解為「正數(shù)」,那么也就不能用「負負得正」的思想了,我們這里使用兩個隊列來實現(xiàn)棧,主要的操作思路是先將元素插入一個臨時隊列中,然后再將另一個隊列的所有元素插入到臨時隊列的尾部,從而實現(xiàn)后進先出功能的,具體的實現(xiàn)步驟如下。

步驟一

添加首個元素,入列到臨時隊列 queue2:

步驟二

因為正式隊列中無元素,因此無需將 queue1?中的元素移動到臨時隊列 queue2?的尾部,直接將臨時隊列和正式隊列互換即可:

步驟三

添加第二個元素,先入列到臨時隊列 queue2:

步驟四

再將 queue1 中的元素移動到 queue2?的尾部,如下所示:


步驟五

再將 queue1 和 queue2 進行互換:

步驟六

執(zhí)行出隊操作:

最終效果

從最終的效果圖我們可以看出,通過兩個隊列已經(jīng)實現(xiàn)了后進先出的特性,也就是完成了從隊列到棧的轉(zhuǎn)換,實現(xiàn)代碼如下:

import?java.util.Queue;class?MyStack?{Queue<Integer>?queue1;Queue<Integer>?queue2;public?MyStack()?{queue1?=?new?LinkedBlockingQueue();queue2?=?new?LinkedBlockingQueue();}/***?入棧*/public?void?push(int?x)?{//?1.入列臨時隊列二queue2.offer(x);//?2.將隊列一的所有元素移動到隊列二while?(!queue1.isEmpty())?{queue2.offer(queue1.poll());}//?3.隊列一和隊列二互換Queue<Integer>?temp?=?queue1;queue1?=?queue2;queue2?=?temp;}/***?出棧并返回此元素*/public?int?pop()?{return?queue1.poll();}/***?查詢棧頂元素*/public?int?top()?{return?queue1.peek();}/***?判斷是否為空*/public?boolean?empty()?{return?queue1.isEmpty();} }

我們在 LeetCode 中提交以上測試代碼,執(zhí)行結(jié)果如下:

此方法很穩(wěn),竟然擊敗了 100% 的用戶。

實現(xiàn)方法 2:一個隊列實現(xiàn)棧

那我們可以不可以用一個隊列來實現(xiàn)棧呢?答案是肯定的。

我們只需要執(zhí)行以下兩個步驟就可以實現(xiàn)將隊列轉(zhuǎn)換為棧了,具體實現(xiàn)步驟如下:

  • 將元素入列到隊尾;

  • 再將除隊尾之外的所有元素移除并重寫入列。

  • 這樣操作之后,最后進入的隊尾元素反而變成了隊頭元素,也就實現(xiàn)了后進先出的功能了,如下圖所示。

    步驟一

    元素 1 入列:

    步驟二

    元素 2 入列:

    步驟三

    將最后一個元素之前的所有元素,也就是元素 1,出列重新入列:

    步驟四

    執(zhí)行出隊操作:

    最終效果

    以上思路的實現(xiàn)代碼如下:

    import?java.util.Queue;class?MyStack?{Queue<Integer>?queue1;public?MyStack()?{queue1?=?new?LinkedBlockingQueue();}/***?入棧*/public?void?push(int?x)?{//?獲取原隊列長度(要移動的次數(shù))int?count?=?queue1.size();//?將元素放入隊尾queue1.offer(x);//?將除最后一個元素外,其他的元素重新入隊for?(int?i?=?0;?i?<?count;?i++)?{System.out.println("for");queue1.offer(queue1.poll());}}/***?出棧并返回此元素*/public?int?pop()?{return?queue1.poll();}/***?查詢棧頂元素*/public?int?top()?{return?queue1.peek();}/***?判斷是否為空*/public?boolean?empty()?{return?queue1.isEmpty();} }

    我們把以上代碼在 LeetCode 中提交,執(zhí)行結(jié)果如下:


    此方法依舊很穩(wěn),也是同樣的擊敗了 100% 的用戶,只不過此方法在內(nèi)存方面有更好的表現(xiàn)。

    實現(xiàn)方法 3:雙端隊列實現(xiàn)棧

    如果覺得以上方法比較難的話,最后我們還有一個更簡單的實現(xiàn)方法,我們可以使用 Java 中的雙端隊列 ArrayDeque?來實現(xiàn)將元素可以插入隊頭或隊尾,同樣移除也是,那么這樣我們就可以從隊尾入再從隊尾出,從而就實現(xiàn)了棧的功能了。

    雙端隊列結(jié)構(gòu)如下:


    我們來演示一下用雙端隊列實現(xiàn)棧的具體步驟。

    步驟一

    元素 1 入隊:

    步驟二

    元素 2 入隊(隊尾):

    步驟三

    再從隊尾出隊:

    最終效果

    以上思路的實現(xiàn)代碼如下:

    import?java.util.ArrayDeque;class?MyStack?{ArrayDeque<Integer>?deque;public?MyStack()?{deque?=?new?ArrayDeque<>();}/***?入棧*/public?void?push(int?x)?{deque.offer(x);}/***?出棧并返回此元素*/public?int?pop()?{return?deque.pollLast();}/***?查詢棧頂元素*/public?int?top()?{return?empty()???-1?:?deque.peekLast();}/***?判斷是否為空*/public?boolean?empty()?{return?deque.isEmpty();} }

    我們把以上代碼在 LeetCode 中提交,執(zhí)行結(jié)果如下:

    總結(jié)

    本文我們用 3 種方法實現(xiàn)了將隊列轉(zhuǎn)換為棧,其中最簡單的方法是用 Java 中自帶的雙端隊列 ArrayDeque?從隊尾入并從隊尾出就實現(xiàn)了棧 ,其他兩個方法使用的是普通隊列,通過入隊之后再移動元素到入隊元素之后的方法,從而實現(xiàn)了棧的功能。

    小伙伴們,你學會了嗎?

    往期推薦

    算法圖解:如何用兩個棧實現(xiàn)一個隊列?


    真不錯,圖解Java中的5大隊列!


    小白學算法:買賣股票的最佳時機!


    關注我,每天陪你進步一點點!

    總結(jié)

    以上是生活随笔為你收集整理的队列实现栈的3种方法,全都击败了100%的用户!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。