1、20. 有效的括號
給定一個只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串,判斷字符串是否有效。
有效字符串需滿足:1、左括號必須用相同類型的右括號閉合。2、左括號必須以正確的順序閉合。
注意空字符串可被認為是有效字符串。
示例 2:
輸入: "()[]{}" 輸出: true
示例 4:
輸入: "([)]" 輸出: false
示例 5:
輸入: "{[]}" 輸出: true
class Solution { public: bool isValid(string s) { stack<char> parentheses; for(int i=0;i<s.size();++i) { if (s[i] == '(' || s[i] == '[' || s[i] == '{') parentheses.push(s[i]); else { if (parentheses.empty()) return false; if (s[i] == ')' && parentheses.top() != '(') return false; if (s[i] == ']' && parentheses.top() != '[') return false; if (s[i] == '}' && parentheses.top() != '{') return false; parentheses.pop(); } } return parentheses.empty(); } };
2、22. 括號生成
給出 n 代表生成括號的對數,請你寫出一個函數,使其能夠生成所有可能的並且有效的括號組合。
例如,給出 n = 3,生成結果為:
[ "((()))", "(()())", "(())()", "()(())", "()()()" ]
這道題給定一個數字n,讓生成共有n個括號的所有正確的形式,對於這種列出所有結果的題首先還是考慮用遞歸Recursion來解,由於字符串只有左括號和右括號兩種字符,而且最終結果必定是左括號3個,右括號3個,所以我們定義兩個變量left和right分別表示剩余左右括號的個數,如果在某次遞歸時,左括號的個數大於右括號的個數,說明此時生成的字符串中右括號的個數大於左括號的個數,即會出現')('這樣的非法串,所以這種情況直接返回,不繼續處理。如果left和right都為0,則說明此時生成的字符串已有3個左括號和3個右括號,且字符串合法,則存入結果中后返回。如果以上兩種情況都不滿足,若此時left大於0,則調用遞歸函數,注意參數的更新,若right大於0,則調用遞歸函數,同樣要更新參數。
class Solution { public: vector<string> generateParenthesis(int n) { vector<string> res; generateDFS(n, n, "", res); return res; } void generateDFS(int left, int right, string out, vector<string> &res) { if(left>right) return ; if(left == 0 && right == 0) res.push_back(out); else { if (left > 0) generateDFS(left - 1, right, out + '(', res); if (right > 0) generateDFS(left, right - 1, out + ')', res); } } };
3、32. 最長有效括號
給定一個只包含 '('
和 ')'
的字符串,找出最長的包含有效括號的子串的長度。
示例 1:
輸入: "(()"
輸出: 2
解釋: 最長有效括號子串為 "()"
示例 2:
輸入: ")()())
" 輸出: 4 解釋: 最長有效括號子串為"()()"
這里我們還是借助棧來求解,需要定義個start變量來記錄合法括號串的起始位置,我們遍歷字符串,如果遇到左括號,則將當前下標壓入棧,如果遇到右括號,如果當前棧為空,則將下一個坐標位置記錄到start,如果棧不為空,則將棧頂元素取出,此時若棧為空,則更新結果和i - start + 1中的較大值,否則更新結果和i - 棧頂元素中的較大值。
class Solution { public: int longestValidParentheses(string s) { int res = 0; int start = 0; stack<int> st; for(int i=0;i<s.size();++i) { if(s[i] == '(') st.push(i); else if(s[i] == ')') { if(st.empty()) start = i+1; else { st.pop(); if(st.empty()) res = max(res, i-start+1); else res = max(res,i-st.top()); } } } return res; } };
class Solution { public: int longestValidParentheses(string s) { int res = 0; int start = 0; stack<int> st; //記錄左括號的位置 for(int i=0;i<s.size();++i) { if(s[i] == '(') //只有“(”入棧,右括號不入棧 st.push(i); else if(s[i] == ')') { if(st.empty()) //如果此時棧里左括號已經被消耗完了,沒有額外的左括號用來配對當前的右括號了,那么當前的右括號就被單出來了,表明當前子串可以結束了,此時的右括號也成為了下一個group的分界點,此時右括號下標為index,所以下一個group的起始點為index+1,相當於skip掉當前的右括號。 start = i+1; else //如果此時棧不空,可能有兩種情況,1)棧正好剩下1個左括號和當前右括號配對 2)棧剩下不止1個左括號 { st.pop(); if(st.empty()) //棧pop()之前正好剩下1個左括號,pop()之后,棧空了,此時group長度為pos-lastPos res = max(res, i-start+1); else res = max(res,i-st.top());//棧有pop()之前剩下不止1個左括號,此時額外多出的左括號使得新的group形成 } } } return res; } };