代碼題(31)— 有效的括號、括號生成、最長有效括號


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 代表生成括號的對數,請你寫出一個函數,使其能夠生成所有可能的並且有效的括號組合。

例如,給出 = 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;
    }
};

 


免責聲明!

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



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