【LeetCode】括号(有效括号、括号生成、最长有效括号)
文章目錄
- 括號★★
- 有效的括號★
- 最長有效括號★★★
- 有效的括號字符串★★
- 使括號有效的最少添加★★
- 有效括號的嵌套深度★★
- 反轉每對括號間的子串★★
括號★★
LeetC面試題 08.09. 括號
【題目】括號。設計一種算法,打印n對括號的所有合法的(例如,開閉一一對應)組合。
說明:解集不能包含重復的子集。
【示例】
輸入:n = 3 ["((()))","(()())","(())()","()(())","()()()" ]【解題思路】使用遞歸來生成括號
-
若在生成過程中右括號數量大于左括號數量則終止遞歸,或者左括號超過限定數目n則終止遞歸
-
若左括號等于右括號等于n,則添加至結果集并且終止遞歸
有效的括號★
LeetCode20. 有效的括號
【題目】給定一個只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判斷字符串是否有效。
有效字符串需滿足:
- 左括號必須用相同類型的右括號閉合。
- 左括號必須以正確的順序閉合。
注意空字符串可被認為是有效字符串
【示例】
----輸入: "()[]{}" 輸出: true ----輸入: "([)]" 輸出: false【解題思路】
方法一:使用棧模擬,遍歷字符串
- 若為左括號則入棧
- 若為右括號則判斷棧頂元素,若棧為空則返回false,若棧頂元素是與之對應的左括號則出棧,否則返回false
- 最后若棧為空,則返回true,否則返回false
方法二:使用String類的函數,用""替換所有的()[]{},最后判斷字符串是否為空即可
class Solution {public boolean isValid(String s) {while(!s.equals("")) {String str = s.replace("()", "").replace("[]", "").replace("{}", "");if(str.equals(s)) return false;s = str;}return true;} }最長有效括號★★★
LeetCode32. 最長有效括號
【題目】給你一個只包含 '(' 和 ')' 的字符串,找出最長有效(格式正確且連續)括號子串的長度。
【示例】
輸入:s = ")()())" 輸出:4 解釋:最長有效括號子串是 "()()"【解題思路】使用棧保存左括號下標,棧初始化為(-1)
- 對于左括號,入棧對應下標
- 對于右括號,出棧一個下標(表示出棧下標對應的左括號對應當前右括號)
- 若棧為空,則說明不能構成有效括號,入棧當前下標(已遍歷最右端不能構成有效括號的下標)
- 若棧不為空,則說明出棧下標對應為有效括號,更新res = Math.max(res, i - stack.peek())
有效的括號字符串★★
LeetCode678. 有效的括號字符串
【題目】給定一個只包含三種字符的字符串:( ,) 和 *,寫一個函數來檢驗這個字符串是否為有效字符串。有效字符串具有如下規則:
- 任何左括號 ( 必須有相應的右括號 )
- 任何右括號 ) 必須有相應的左括號 (
- 左括號 ( 必須在對應的右括號之前 )
- *可以被視為單個右括號 ) ,或單個左括號 ( ,或一個空字符串
- 一個空字符串也被視為有效字符串
**注意:**字符串大小將在 [1,100] 范圍內。
【示例】
---輸入: "()" 輸出: True ---輸入: "(*))" 輸出: True【解題思路】
方法一:雙棧模擬,棧left保存左括號下標,棧star保存*下標,遍歷字符串
- 若當前字符為(,則將下標i進棧left
- 若當前字符為*,則將其下標i進棧start
- 若當前字符為),若left不為空,優先配對出棧;若left為空且star不為空,則star出棧(表示當前出棧的下標處*可以表示一個左括號);若left和star均為空,則沒有與其配對的,返回false
然后再來看left和star中元素,此時表示*代替右括號來配對left棧中剩余的左括號
- 若left棧頂元素大于star棧頂元素,表示*下標處于左括號下標左邊,返回false
- 否則均出棧一個元素,表示配對
最后若left不為空,表示剩余左括號無法配對,返回false,若為空,返回true
class Solution {public boolean checkValidString(String s) {Stack<Integer> left = new Stack<Integer>();Stack<Integer> star = new Stack<Integer>();for(int i = 0; i < s.length(); i++) {char c = s.charAt(i);if(c == '(') {left.push(i);}else if(c == '*') {star.push(i);}else {if(!left.isEmpty()) {left.pop();}else if(!star.isEmpty()) {star.pop();}else {return false;}}}while(!left.isEmpty() && !star.isEmpty()) {if(left.pop() > star.pop()) return false;}return left.isEmpty();} }方法二:使用兩個變量lo和hi分別表示未匹配左括號的上界和下界
class Solution {public boolean checkValidString(String s) {int lo = 0, hi = 0; //未匹配左括號數量的范圍for(char c : s.toCharArray()) {if(c == '(') {lo++;hi++;}else if(c == ')') {lo = Math.max(0, lo - 1);hi--;if(hi < 0) return false; //右括號多于左括號且不能匹配}else {lo = Math.max(0, lo - 1);hi++;}}return lo == 0;} }使括號有效的最少添加★★
LeetCode使括號有效的最少添加
【題目】給定一個由 ‘(’ 和 ‘)’ 括號組成的字符串 S,我們需要添加最少的括號( ‘(’ 或是 ‘)’,可以在任何位置),以使得到的括號字符串有效。
從形式上講,只有滿足下面幾點之一,括號字符串才是有效的:
- 它是一個空字符串,或者
- 它可以被寫成 AB (A 與 B 連接), 其中 A 和 B 都是有效字符串,或者
- 它可以被寫作 (A),其中 A 是有效字符串。
給定一個括號字符串,返回為使結果字符串有效而必須添加的最少括號數。
【示例】
---輸入:"(((" 輸出:3 ---輸入:"()))((" 輸出:4【解題思路】最少添加至每個括號剛好匹配,即補充括號使不匹配的括號匹配
方法一:遍歷統計,使用countLeft標記左括號的個數,leastAdd記錄添加個數
- 若為左括號,則countLeft++
- 若為右括號,若countLeft值大于0,則表示當前右括號有相應左括號與其配對,若countLeft值等于0,則表示沒有與之對應的左括號配對,即需要添加一個(leastAdd++)
最后返回leastAdd + countLeft,此時countLeft表示沒有與之配對的右括號的數量
class Solution {public int minAddToMakeValid(String S) {int countLeft = 0; //標記左括號的個數int leastAdd = 0; //最少添加個數for(char c : S.toCharArray()){if(c == '(') {countLeft++;}else {if(countLeft == 0) {leastAdd++;}else {countLeft--;}}} return leastAdd + countLeft;} }方法二:使用空字符串替換所有的(),最后剩余字符串的長度就是其未匹配的括號數量
class Solution {public int minAddToMakeValid(String S) {while(S.contains("()")) {S = S.replace("()", "");}return S.length();} }有效括號的嵌套深度★★
LeetCode有效括號的嵌套深度
【題目】有效括號字符串 定義:對于每個左括號,都能找到與之對應的右括號,反之亦然。詳情參見題末「有效括號字符串」部分。
嵌套深度 depth 定義:即有效括號字符串嵌套的層數,depth(A) 表示有效括號字符串 A 的嵌套深度。詳情參見題末**「嵌套深度」**部分。
有效括號字符串類型與對應的嵌套深度計算方法如下圖所示:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-hyBBnVS8-1610270685893)(…\LeetCode\great\有效括號嵌套深度.png)]
給你一個「有效括號字符串」 seq,請你將其分成兩個不相交的有效括號字符串,A 和 B,并使這兩個字符串的深度最小。
- 不相交:每個 seq[i] 只能分給 A 和 B 二者中的一個,不能既屬于 A 也屬于 B 。
- A 或 B 中的元素在原字符串中可以不連續。
- A.length + B.length = seq.length
- 深度最小:max(depth(A), depth(B)) 的可能取值最小。
劃分方案用一個長度為 seq.length 的答案數組 answer 表示,編碼規則如下:
- answer[i] = 0,seq[i] 分給 A 。
- answer[i] = 1,seq[i] 分給 B 。
如果存在多個滿足要求的答案,只需返回其中任意 一個 即可。
【示例】
----輸入:seq = "(()())" 輸出:[0,1,1,1,1,0] ----輸入:seq = "()(())()" 輸出:[0,0,0,1,1,0,1,1] 解釋:本示例答案不唯一。 按此輸出 A = "()()", B = "()()", max(depth(A), depth(B)) = 1,它們的深度最小。 像 [1,1,1,0,0,1,1,1],也是正確結果,其中 A = "()()()", B = "()", max(depth(A), depth(B)) = 1【解題思路】
對于示例:( ( ) ( ( ) ) ( ) ) 嵌套深度:1 2 2 2 3 3 2 2 2 1 分配方案:A B B B A A B B B A 可見奇數的嵌套深度分配給A,偶數的嵌套深度分配給B class Solution {public int[] maxDepthAfterSplit(String seq) {int[] res = new int[seq.length()];int deep = 0;for(int i = 0; i < seq.length(); i++) {if(seq.charAt(i) == '(') {deep++;res[i] = deep & 1;}else {res[i] = deep & 1;deep--;}}return res;} }反轉每對括號間的子串★★
1190. 反轉每對括號間的子串
【題目】給出一個字符串 s(僅含有小寫英文字母和括號)。
請你按照從括號內到外的順序,逐層反轉每對匹配括號中的字符串,并返回最終的結果。
注意:您的結果中不應包含任何括號。
提示:
- 0 <= s.length <= 2000
- s 中只有小寫英文字母和括號
- 我們確保所有括號都是成對出現的
【示例】
輸入:s = "(u(love)i)" 輸出:"iloveu" ---------------------------------- 輸入:s = "(ed(et(oc))el)" 輸出:"leetcode"【解題思路】
每匹配一對括號就將對應區間內的字符反轉
class Solution {public String reverseParentheses(String s) {StringBuffer sb = new StringBuffer();char[] cs = s.toCharArray();Stack<Integer> stack = new Stack<>();for (int i = 0; i < cs.length; i++) {if (cs[i] == '(') {stack.push(i);} else if (cs[i] == ')') {reverse(cs, stack.pop() + 1, i - 1);}}for (char c : cs) {if (c != '(' && c != ')') {sb.append(c);}}return sb.toString();}private void reverse(char[] cs, int le, int ri) {while (le < ri) {char c = cs[le];cs[le++] = cs[ri];cs[ri--] = c;}} }🎈
2021/5/27新增題目“反轉每對括號間的子串”
總結
以上是生活随笔為你收集整理的【LeetCode】括号(有效括号、括号生成、最长有效括号)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: configure 查找依赖库_Rust
- 下一篇: 数学知多少