[LeetCode] 1021. Remove Outermost Parentheses 去除最外層括號



A valid parentheses string is either empty ("")"(" + A + ")", or A + B, where A and B are valid parentheses strings, and + represents string concatenation.  For example, """()""(())()", and "(()(()))" are all valid parentheses strings.

A valid parentheses string S is primitive if it is nonempty, and there does not exist a way to split it into S = A+B, with A and B nonempty valid parentheses strings.

Given a valid parentheses string S, consider its primitive decomposition: S = P_1 + P_2 + ... + P_k, where P_i are primitive valid parentheses strings.

Return S after removing the outermost parentheses of every primitive string in the primitive decomposition of S.

Example 1:

Input: "(()())(())"
Output: "()()()"
Explanation:
The input string is "(()())(())", with primitive decomposition "(()())" + "(())".
After removing outer parentheses of each part, this is "()()" + "()" = "()()()".

Example 2:

Input: "(()())(())(()(()))"
Output: "()()()()(())"
Explanation:
The input string is "(()())(())(()(()))", with primitive decomposition "(()())" + "(())" + "(()(()))".
After removing outer parentheses of each part, this is "()()" + "()" + "()(())" = "()()()()(())".

Example 3:

Input: "()()"
Output: ""
Explanation:
The input string is "()()", with primitive decomposition "()" + "()".
After removing outer parentheses of each part, this is "" + "" = "".

Note:

  1. S.length <= 10000
  2. S[i] is "(" or ")"
  3. S is a valid parentheses string

這道題給了一個合法的括號字符串,其可能由多個合法的括號字符子串組成,現在讓把所有合法的子串的最外層的括號去掉,將剩下的拼接起來並返回,根據題目給的例子,不難理解題意。LeetCode 中關於括號的題目還是比較多的,比如 Valid ParenthesesValid Parenthesis StringRemove Invalid Parentheses,和 Longest Valid Parentheses 等。大多都是考察如何判斷一個括號字符串是否合法,所謂的合法,大致就是左右括號個數要相同,每個右括號前面必須要有對應的左括號,一個比較簡單的判斷方法就是用一個變量 cnt,遇到左括號則自增1,遇到右括號則自減1,在這過程中 cnt 不能為負,且最后 cnt 必須為0。這道題限定了括號字符串一定是合法的,但也可以用這個方法來找出每個合法的子串部分,遍歷字符串S,若當前字符為左括號,則 cnt 自增1,否則自減1。若 cnt 不為0,說明還不是一個合法的括號子串,跳過。否則我們就知道了一個合法括號子串的結束位置,用一個變量 start 記錄合法括號子串的起始位置,初始化為0,這樣就可以將去除最外層括號后的中間部分直接取出來加入結果 res 中,然后此時更新 start 為下一個合法子串的起始位置繼續遍歷即可,參見代碼如下:


解法一:

class Solution {
public:
    string removeOuterParentheses(string S) {
        string res = "";
        int cnt = 0, start = 0, n = S.size();
        for (int i = 0; i < n; ++i) {
            (S[i] == '(') ? ++cnt : --cnt;
            if (cnt != 0) continue;
            res += S.substr(start + 1, i - start - 1);
            start = i + 1;
        }
        return res;
    }
};

我們也可以寫的更簡潔一些,並不需要等到找到整個合法括號子串后再加入結果 res,而是在遍歷的過程中就加入。因為這里的括號分為兩種,一種是合法子串的最外層括號,這種不能加到結果 res,另一種是其他位置上的括號,這種要加到 res。所以只要區分出這兩種情況,就知道當前括號要不要加,區別的方法還是根據 cnt,當遇到左括號時,若此時 cnt 大於0,則一定不是合法子串的起始位置,可以加入 res,之后 cnt 自增1;同理,若遇到右括號,若此時 cnt 大於1,則一定不是合法子串的結束位置,可以加入 res,之后 cnt 自減1,參見代碼如下:


解法二:

class Solution {
public:
    string removeOuterParentheses(string S) {
        string res;
        int cnt = 0;
        for (char c : S) {
            if (c == '(' && cnt++ > 0) res.push_back(c);
            if (c == ')' && cnt-- > 1) res.push_back(c);
        }
        return res;
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/1021


類似題目:

Valid Parentheses

Valid Parenthesis String

Remove Invalid Parentheses

Longest Valid Parentheses


參考資料:

https://leetcode.com/problems/remove-outermost-parentheses/

https://leetcode.com/problems/remove-outermost-parentheses/discuss/270022/JavaC%2B%2BPython-Count-Opened-Parenthesis

https://leetcode.com/problems/remove-outermost-parentheses/discuss/270566/My-Java-3ms-Straight-Forward-Solution-or-Beats-100


LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

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



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