1. 程式人生 > 實用技巧 >[程式設計題]劍指 Offer 09 用兩個棧實現佇列(四種方式[本質是2種方法])

[程式設計題]劍指 Offer 09 用兩個棧實現佇列(四種方式[本質是2種方法])

lc 劍指 Offer 09. 用兩個棧實現佇列

題目描述

輸入輸出描述

思路

1、使用傳統的棧Stack即可完成

2、使用Deque資料結構堵住一端(堵住首)----(addLast(),removeLast) 或者堵住尾(addFirst();removeFirst)

3、使用Deque資料結構堵住一端(堵住尾(addFirst();removeFirst)

4、直接使用Deque模擬棧方法push,pop;即可 (其中就是底層使用的3的方法)

方法1:使用傳統的棧Stack即可完成

Java程式碼:

import java.util.Stack;

public class Solution {
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();
    
    public void push(int node) {
        stack1.push(node);
    }
    
    public int pop() {
        //pop的時候直接看棧2是否為空
        if(stack2.isEmpty()){
            while(!stack1.isEmpty()){
                stack2.push(stack1.pop());
            }
            //都存入棧2中的時候,呼叫一次pop方法,彈出一個stack2的棧頂元素(但是每次彈出都判斷棧是否空)
            if(!stack2.isEmpty()) {
                return stack2.pop();
            }else { return -1; }    
        }else{
            //棧2不為空,直接彈出我們需要的棧頂元素(每次彈出每次檢測棧是否空)
            if(!stack2.isEmpty()) {
                return stack2.pop();
            }else { return -1; }   
        }
    }
}

輸出:

時間和記憶體如下:

方法2:使用Deque資料結構堵住一端(堵住尾(addFirst();removeFirst)

相當於我們堵住雙端列表的尾部,從前邊存取。

addFirst();removeFirst)

如下:

Java程式碼

import java.util.*;

public class Solution {
    Deque<Integer> stack1 = new LinkedList<>();
    Deque<Integer> stack2 = new LinkedList<>();
    
    public void push(int node) {
       stack1.addFirst(node);
    }
    
    public int pop() {
        //如果棧2空,先進行轉移操作
        if(stack2.isEmpty()){
            while(!stack1.isEmpty()){
                stack2.addFirst(stack1.removeFirst());
            }
            //把stack1元素都放入到stack2後可以彈出棧首,(每次都要檢測是否棧為空)
            if(!stack2.isEmpty()){return stack2.removeFirst();}
            else {return -1;}
        }else{
            //棧2不為空
            //彈出棧首,(每次都要檢測是否棧為空)
            if(!stack2.isEmpty()){return stack2.removeFirst();}
            else {return -1;}
        }
       
    }
}

輸出:

方法3:使用Deque資料結構堵住一端(堵住首)----(addLast(),removeLast)

思想

addLast(),removeLast)

Java程式碼

import java.util.*;
class CQueue {
    
    Deque<Integer> stack1;
    Deque<Integer> stack2;


    public CQueue() {
        stack1 = new LinkedList<Integer>();
        stack2 = new LinkedList<Integer>();
    }
    
    //Deque是雙端的佇列,我們只要保證一端不變就是棧,比如頭不變,往後插,從後取就是棧
    public void appendTail(int value) {
        stack1.addLast(value);
    }
    
    public int deleteHead() {
        if(stack2.isEmpty()){
            while(!stack1.isEmpty()){
                stack2.addLast(stack1.removeLast());
            }
            //放完之後取出stack2的最後的一個元素(因為模擬棧的話,統一看做First是堵住的)
            //注意出隊的時候一定要時刻判斷隊是否為空
            if(!stack2.isEmpty()){return stack2.removeLast();}else{return -1;} 
        }else{
            //stack2不為空,就直接彈出
            //注意出隊的時候一定要時刻判斷隊是否為空
            if(!stack2.isEmpty()){return stack2.removeLast();}else{return -1;}
        }
    }
}

方法4:直接使用Deque模擬棧方法push,pop;即可 (其中就是底層和方法2addFisrt原理相同)

java程式碼:

import java.util.*;

public class Solution {
    Deque<Integer> stack1 = new LinkedList<Integer>();
    Deque<Integer> stack2 = new LinkedList<Integer>();
    
    public void push(int node) {
        stack1.push(node);
    }
    
    public int pop() {
        //如果棧2為空,就先轉移棧1元素如棧2
        if(stack2.isEmpty()){
            while(!stack1.isEmpty()){
                stack2.push(stack1.pop());
            }
            //壓棧完成後,就可以本次的彈出操作(每次都要檢測本次出棧棧2空了嗎)
            if(!stack2.isEmpty()){return stack2.pop();}
            else return -1;
        }else{
            //如果棧2本身不為空,直接出棧
            if(!stack2.isEmpty()){return stack2.pop();}
            else return -1;
        }
    }
}

輸出: