編輯器如何判定括號合法性

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

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

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

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

Input: "([)]"
Output: false

Input: "{[]}"
Output: true

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

PS:我認真寫了 100 多篇原創,手把手刷 200 道力扣題目,全部發布在 labuladong的算法小抄,持續更新。建議收藏,按照我的文章順序刷題,掌握各種算法套路後投再入題海就如魚得水了。

一、處理一種括號

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

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

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

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

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 '[';
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章