如何判定括號合法性


對括號的合法性判斷是一個很常見且實用的問題,比如說我們寫的代碼,編輯器和編譯器都會檢查括號是否正確閉合。而且我們的代碼可能會包含三種括號 [](){},判斷起來有一點難度。

本文就來聊一道關於括號合法性判斷的算法題,相信能加深你對這種數據結構的理解。

題目很簡單,輸入一個字符串,其中包含 [](){} 六種括號,請你判斷這個字符串組成的括號是否合法。

Input: "()[]{}"
Output: true

Input: "([)]"
Output: false

Input: "{[]}"
Output: true

解決這個問題之前,我們先降低難度,思考一下,如果只有一種括號 (),應該如何判斷字符串組成的括號是否合法呢?

一、處理一種括號

字符串中只有圓括號,如果想讓括號字符串合法,那么必須做到:

每個右括號 ) 的左邊必須有一個左括號 ( 和它匹配

比如說字符串 ()))(( 中,中間的兩個右括號左邊就沒有左括號匹配,所以這個括號組合是不合法的。

那么根據這個思路,我們可以寫出算法:

bool isValid(string str) {
    // 待匹配的左括號數量
    int left = 0;
    for (char c : str) {
        if (c == '(')
            left++;
        else // 遇到右括號
            left--;

        if (left < 0)
            return false;
    }
    return left == 0;
}

如果只有圓括號,這樣就能正確判斷合法性。對於三種括號的情況,我一開始想模仿這個思路,定義三個變量 left1left2left3 分別處理每種括號,雖然要多寫不少 if else 分支,但是似乎可以解決問題。

但實際上直接照搬這種思路是不行的,比如說只有一個括號的情況下 (()) 是合法的,但是多種括號的情況下, [(]) 顯然是不合法的。

僅僅記錄每種左括號出現的次數已經不能做出正確判斷了,我們要加大存儲的信息量,可以利用棧來模仿類似的思路。

二、處理多種括號

棧是一種先進后出的數據結構,處理括號問題的時候尤其有用。

我們這道題就用一個名為 left 的棧代替之前思路中的 left 變量,遇到左括號就入棧,遇到右括號就去棧中尋找最近的左括號,看是否匹配

bool isValid(string str) {
    stack<char> left;
    for (char c : str) {
        if (c == '(' || c == '{' || c == '[')
            left.push(c);
        else // 字符 c 是右括號
            if (!left.empty() && leftOf(c) == left.top())
                left.pop();
            else
                // 和最近的左括號不匹配
                return false;
    }
    // 是否所有的左括號都被匹配了
    return left.empty();
}

char leftOf(char c) {
    if (c == '}') return '{';
    if (c == ')') return '(';
    return '[';
}

我最近精心制作了一份電子書《labuladong的算法小抄》,分為【動態規划】【數據結構】【算法思維】【高頻面試】四個章節,共 60 多篇原創文章,絕對精品!限時開放下載,在我的公眾號 labuladong 后台回復關鍵詞【pdf】即可免費下載!

目錄

歡迎關注我的公眾號 labuladong,技術公眾號的清流,堅持原創,致力於把問題講清楚!

labuladong


免責聲明!

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



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