對括號的合法性判斷是一個很常見且實用的問題,比如說我們寫的代碼,編輯器和編譯器都會檢查括號是否正確閉合。而且我們的代碼可能會包含三種括號 [](){}
,判斷起來有一點難度。
本文就來聊一道關於括號合法性判斷的算法題,相信能加深你對棧這種數據結構的理解。
題目很簡單,輸入一個字符串,其中包含 [](){}
六種括號,請你判斷這個字符串組成的括號是否合法。
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;
}
如果只有圓括號,這樣就能正確判斷合法性。對於三種括號的情況,我一開始想模仿這個思路,定義三個變量 left1
,left2
,left3
分別處理每種括號,雖然要多寫不少 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,技術公眾號的清流,堅持原創,致力於把問題講清楚!