Leetcode 22 括号生成 Generate Parentheses

给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。

例如,给出 n = 3,生成结果为:

[
  "((()))",
  "(()())",
  "(())()",
  "()(())",
  "()()()"
]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/generate-parentheses
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

方法一:暴力法

暴力法就是将所有可能的排列都列举出来,再判断是否符合条件。

该方法中会用到全排列next_permutation()函数,须包含<algorithm>头文件,一般先排序,使用方法如下:

#include <stdio.h>
#include <algorithm>
using namespace std;
int main(){
    int n;
    while(scanf("%d",&n)&&n){
        int a[1000];
        for(int i=0;i<n;i++){
            scanf("%d",&a[i]);
        }
        sort(a,a+n);
        do{
            for(int i=0;i<n;i++)
                printf("%d ",a[i]);
            printf("\n");
        }while(next_permutation(a,a+n));
    }
    return 0;
}

 最终代码如下:

class Solution {
public:
    vector<string> generateParenthesis(int n) {
        vector<string> res;
        if (n <= 0) return res;
        if (n == 1) {
            res.push_back("()");
            return res;
        }
        int i;
        string s="";
        for (i = 0; i < n; i++) {
            s += "()";
        }
        sort(s.begin(), s.end());
        do {
            if (isvalid(s)) {
                res.push_back(s);
            }
        } while (next_permutation(s.begin() + 1, s.end()));
        return res;
    }

    bool isvalid(string s) {
        int cnt = 0;
        for (int i = 0; i < s.size(); i++) {
            if (s[i] == '(') {
                cnt++;
            }
            else {
                cnt--;
            }
            if (cnt < 0) return false;
        }
        if (cnt == 0) return true;
        else return false;
    }
};

方法二:回溯算法(DFS)

具体思路如下:left、right分别表示左括号和右括号可用的数量,若两者都为0,则该表达式合法,加入最后的解集,若使用的右括号多于左括号,则该表达式不合法。剩下的都是不完整的合法表达式,若还有可用的左括号,则dfs下一步,右括号同理。

一开始把res在dfs函数的参数中,push_back等操作都正常,但是输出为空,当把res改成全局变量后就没有问题了。

class Solution {
public:
    vector<string> res;
    void dfs(string curStr, int left, int right) {
        if (left == 0 && right == 0) {
            res.push_back(curStr);
            return;
        }
        if (left > right) {
            return;
        }
        if (left > 0) {
            dfs(curStr + '(', left - 1, right);
        }
        if (right > 0) {
            dfs(curStr + ')', left, right - 1);
        }
    }
    vector<string> generateParenthesis(int n) {
        if (n <= 0) return res;
        if (n == 1) {
            res.push_back("()");
            return res;
        }
        dfs("", n, n);
        return res;
    }
};

方法三:BFS

在每一个字符的添加过程中都增加检查的步骤。使用了队列,每次添加都先判断一下合理性。每次循环都遍历了固定位数的所有可能性,如第一次遍历了1位,第二次栈中存储了2位所有的可能性,第三次栈中存储了3位所有的可能性..

class Solution {
public:
    vector<string> generateParenthesis(int n) {
        vector<string> res;
        if (n <= 0) return res;
        queue<string> que;
        stack<char> store;
        que.push("(");
        int i;
        while(!que.empty()) {
            string tmp = que.front();
            int leftcnt = 0;
            for (i = 0; i < tmp.size(); i++) {
                if (tmp[i] == '(') {
                    leftcnt++;
                }
            }
            if (tmp.size() == n * 2) {
                res.push_back(tmp);
                que.pop();
            }
            else {
                if (leftcnt < n) {
                    que.push(tmp + "(");
                }
                bool valid = true;
                for (i = 0; i < tmp.size(); i++) {
                    if (tmp[i] == '(') {
                        store.push(tmp[i]);
                    }
                    if (tmp[i] == ')') {
                        if (store.empty()) {
                            valid = false;
                        }
                        else store.pop();
                    }
                }
                if(store.empty()) valid=false;
                
                if (valid==true && !store.empty()) {
                    que.push(tmp + ")");
                }
                
                while(!store.empty()) {store.pop();}
                que.pop();
            }
        }
        return res;
    }
};

方法四:动态规划(DP)

动态规划最核心的内容是:

dp[n]="("+dp[i]+")"+dp[n-i-1],i∈(0,1,...,n-1)

也就是说,n对括号的情况可以由许多小于n对括号的不同情况组合而成

class Solution {
public:
    vector<string> generateParenthesis(int n) {
        vector<string> res;
        if (n <= 0) return res;
        if (n == 1) {
            res.push_back("()");
            return res;
        }
        unordered_map<int, vector<string>> dp;
        vector<string> dp0,dp1;
        dp0.push_back("");
        dp[0] = dp0;
        dp1.push_back("()");
        dp[1] = dp1;
        int i, j;
        for (int i = 2; i <= n; i++) {//每次循环形成dp[i]的内容
            vector<string> cur;
            for (int j = 0; j < i; j++) {//str1遍历所有长度
                vector<string> str1 = dp[j];
                vector<string> str2 = dp[i - 1 - j];
                for (auto s1 : str1) {
                    for (auto s2 : str2) {
                        cur.push_back("(" + s1 + ")" + s2);
                    }
                }
            }
            dp[i] = cur;
        }
        return dp[n];
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值