22 括号生成

题目描述:
数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

示例:
输入:n = 3
输出:[
“((()))”,
“(()())”,
“(())()”,
“()(())”,
“()()()”
]

方法1:动态规划
主要思路:
(1)这道题如果想到思路的,其实挺简单的,主要就是使用已生成的括号组成,来组合成新生成的括号组成;
(2)使用动态数组vector<vector> dp(n+1);其中dp[ i ] 表示当 i 对括号时,可以生成的合法的括号组合,那么对于 dp[ i ] 的组合,可以通过 dp[ j ]和dp[ i-j-1 ] 的组合,再次组合 而成,在合适的位置插入新的 “()” 即可;
(3)直观的想,就是dp[ j ]中的 j 对括号,dp[ i-j-1 ]中的 i-j-i 对括号,再加上新增的 1 个括号,总共就是 i 对括号,现在只需要把他们组成一起即可;

class Solution {
public:
    vector<string> generateParenthesis(int n) {
    	//特殊的情形
        if(n==0)
            return vector<string>(1,"");
        if(n==1)
            return vector<string>(1,"()");
        //定义的动态数组
        vector<vector<string>> dp(n+1);
        //初始状态
        dp[0]=vector<string>(1,"");
        dp[1]=vector<string>(1,"()");
		//第一层是 需要确定的新的 括号对数
        for(int i=2;i<=n;++i){
        	//第二层用来辅助确定另外两个需要的子组合
            for(int j=0;j<i;++j){
            	//第一个子组合
                for(string& str1:dp[j]){
                	//第二个子组合
                    for(string& str2:dp[i-j-1]){
                        dp[i].push_back("("+str1+")"+str2);//两个子组合和一对括号组成的 i 对括号组合
                    }
                }
            }
        }

        return dp[n];//返回n对括号的组合
    }
};

方法2:回溯
主要思路:
(1)回溯的主要思路就是在能做的选择中做选择,到满足要求的时候,存储结果,到不满足要求的时候,提前返回,返回后,记得恢复原始的状态;
(2)这里的选择就是左,右括号,满足的条件是左右括号的数量都减少到0,不满足要求的结果是左边括号数量大于右边的括号数量,或者左边括号数量小于0,或者右边括号数量小于0;
(3)在做选择时,直接将左括号或右括号压入到中间变量str 的结尾,并在返回的时候,弹出即可;

class Solution {
public:

    void helper(vector<string>& res,string& str,int& left,int& right){
    	//不满足要求的情形
        if(left>right||left<0||right<0)
            return ;
        //满足要求的情形
        if(!left&&!right){
            res.push_back(str);
            return ;
        }
		//选择左括号
        str.push_back('(');
        --left;
        helper(res,str,left,right);
        ++left;
        str.pop_back();//弹出
		//压入右括号
        str.push_back(')');
        --right;
        helper(res,str,left,right);
        ++right;
        str.pop_back();//弹出

    }

    vector<string> generateParenthesis(int n) {
        if(n==0)
            return vector<string>(1,"");
        if(n==1)
            return vector<string>(1,"()");
        string str;
        vector<string> res;
        int left=n;
        int right=n;
        helper(res,str,left,right);
        return res;
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值