幾道和「堆疊、佇列」有關的面試演算法題

程式設計師吳師兄發表於2019-03-05

題目一:有效的括號

問題描述

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

解題思路

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

這裡我們使用

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

動畫演示

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

程式碼實現

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

圖 2

圖 3

小程式

相關文章