幾道和「堆棧、隊列」有關的面試算法題


題目一:有效的括號

問題描述

給定一個只包括 '(',')','{','}','[',']' 的字符串,判斷字符串是否有效。

解題思路

這道題讓我們驗證輸入的字符串是否為括號字符串,包括大括號,中括號和小括號。

這里我們使用

  • 遍歷輸入字符串
  • 如果當前字符為左半邊括號時,則將其壓入棧中
  • 如果遇到右半邊括號時,分類討論:
  • 1)如棧不為空且為對應的左半邊括號,則取出棧頂元素,繼續循環
  • 2)若此時棧為空,則直接返回 false
  • 3)若不為對應的左半邊括號,反之返回 false

動畫演示

20. Valid Parentheses 20. Valid Parentheses

代碼實現

class Solution {
    public boolean isValid(String s) {
        Stack<Character> stack = new Stack<>();
        char[] chars = s.toCharArray();
        for (char aChar : chars) {
            if (stack.size() == 0) {
                stack.push(aChar);
            } else if (isSym(stack.peek(), aChar)) {
                stack.pop();
            } else {
                stack.push(aChar);
            }
        }
        return stack.size() == 0;
    }

    private boolean isSym(char c1, char c2) {
        return (c1 == '(' && c2 == ')') || (c1 == '[' && c2 == ']') || (c1 == '{' && c2 == '}');
    }
}

題目二:用兩個棧實現隊列

問題描述

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

解題思路

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

  • push 元素時,始終是進入棧,pop 和 peek 元素時始終是走出棧。
  • pop 和 peek 操作,如果出棧為空,則需要從入棧將所有元素移到出棧,也就是調換順序,比如開始push的順序是 3-2-1,1 是最先進入的元素,則到出棧的順序是 1-2-3,那 pop 操作拿到的就是 1,滿足了先進先出的特點。
  • pop 和 peek 操作,如果出棧不為空,則不需要從入棧中移到數據到出棧。

動畫 1動畫 1

代碼實現

Stack<Integer> in = new Stack<Integer>();
Stack<Integer> out = new Stack<Integer>();

public void push(int node) {
    in.push(node);
}

public int pop() throws Exception {
    if (out.isEmpty())
        while (!in.isEmpty())
            out.push(in.pop());

    if (out.isEmpty())
        throw new Exception("queue is empty");

    return out.pop();
}

題目三:棧的壓入、彈出序列

問題描述

輸入兩個整數序列,第一個序列表示棧的壓入順序,請判斷第二個序列是否為該棧的彈出順序。假設壓入棧的所有數字均不相等。例如序列 1,2,3,4,5 是某棧的壓入順序,序列 4,5,3,2,1是該壓棧序列對應的一個彈出序列,但4,3,5,1,2就不可能是該壓棧序列的彈出序列。(注意:這兩個序列的長度是相等的)

解題思路

借用一個輔助的棧,遍歷壓棧順序,先講第一個放入棧中,這里是 1,然后判斷棧頂元素是不是出棧順序的第一個元素,這里是 4,很顯然 1≠4 ,所以需要繼續壓棧,直到相等以后開始出棧。

出棧一個元素,則將出棧順序向后移動一位,直到不相等,這樣循環等壓棧順序遍歷完成,如果輔助棧還不為空,說明彈出序列不是該棧的彈出順序。

代碼實現

public boolean IsPopOrder(int[] pushSequence, int[] popSequence) {
    int n = pushSequence.length;
    Stack<Integer> stack = new Stack<>();
    for (int pushIndex = 0, popIndex = 0; pushIndex < n; pushIndex++) {
        stack.push(pushSequence[pushIndex]);
        while (popIndex < n && !stack.isEmpty() 
                && stack.peek() == popSequence[popIndex]) {
            stack.pop();
            popIndex++;
        }
    }
    return stack.isEmpty();
}

題目四:包含 min 函數的棧

問題描述

定義棧的數據結構,請在該類型中實現一個能夠得到棧最小元素的 min 函數。

解題思路

使用兩個 stack,一個作為數據棧,另一個作為輔助棧。其中 數據棧 用於存儲所有數據,而 輔助棧 用於存儲最小值。

舉個🌰:

  1. 入棧的時候:首先往空的數據棧里壓入數字 3 ,此時 3 是最小值,所以把最小值壓入輔助棧。接下來往數據棧里壓入數字 4 。由於 4 大於之前的最小值,因此只要入數據棧,不需要壓入輔助棧。

  2. 出棧的時候:當數據棧和輔助棧的棧頂元素相同的時候,輔助棧的棧頂元素出棧。否則,數據棧的棧頂元素出棧。

  3. 獲得棧頂元素的時候:直接返回數據棧的棧頂元素。

  4. 棧最小元素:直接返回輔助棧的棧頂元素。

代碼實現

private Stack<Integer> dataStack = new Stack<>();
private Stack<Integer> minStack = new Stack<>();

public void push(int node) {
    dataStack.push(node);
    minStack.push(minStack.isEmpty() ? node : Math.min(minStack.peek(), node));
}

public void pop() {
    dataStack.pop();
    minStack.pop();
}

public int top() {
    return dataStack.peek();
}

public int min() {
    return minStack.peek();
}

小程序

小程序名稱:圖解劍指offer

劍指offer上面的 66 道題目都挪上去了,每一道題目基本上都有詳細說明解法,更多的解法我還在添加中,需要准備刷題的可以在坐地鐵的零碎時間拿出來看看^_^

圖 1圖 1 圖 2圖 2 圖 3


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM