22. 括号生成

题目描述

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

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

方法1

思路

动态规划的第一步操作:从左往右第一个括号及其内的情况(也就是第一个"("到和它匹配的")"
之间的情况),剩下的就是子问题了

代码实现1

动态规划递归实现

class Solution {
public:
    vector<string> generateParenthesis(int n) 
    {
        vector<string> ret;
        if(n<1)
            return ret;
        return generateParenthesisCore(n);       
    }

    vector<string> generateParenthesisCore(int n)
    {
        if(n == 0)
            return {""};
        if(n == 1)
            return {"()"};
        vector<string> ret;
        for(int i = 0;i<n;i++)
        {   
            vector<string> in = generateParenthesisCore(i);
            vector<string> out = generateParenthesisCore(n-1-i);
            for(auto elem1:in)           
                for(auto elem2:out)                
                    ret.push_back("("+elem1+")"+elem2);
        }
        return ret;
    }
};

代码实现2

动态规划使用额外存储空间实现

class Solution {
public:
    vector<string> generateParenthesis(int n) {
        vector<string> ret;
        if(n<1)
        	return ret;
    	unordered_map<int,vector<string>>dp;
    	dp[0]={""};
    	dp[1]={"()"};
    	for(int i = 2;i<=n;i++)
    	{
    		vector<string> temp;
    		for(int j = 0;j<i;j++)
    		{
    			for(auto elem1:dp[j])
    			{
    				for(auto elem2:dp[i-1-j])
    				{
    					temp.push_back("("+elem1+")"+elem2);
    				}
    			}
    		}
        
    		dp[i] = temp;
    	}

    	return dp[n];
        
    }
};

方法2

思路

n对括号,其实就是枚举2n个位置的放置情况,这里递归函数中的l,r加在一起起的作用类似于index的作用。右括号只能用它前面的左括号抵消(所以此位置放置右括号时必须确保此位置之前的左括号数大于
右括号数),这可以用归纳法来证明(此位置之前出现的所有")"都能匹配抵消掉,由于左括号数大于
右括号数,所以还有剩余的"(",就能和这个位置的")"匹配上)。而左括号只能与后面的右括号匹配,所以对于左括号没有限制条件。此问题每个位置放置的元素有两种可能,不限制重复,只是要注意是否能够满足放置的条件。

代码实现

class Solution {
public:
    
    vector<string> generateParenthesis(int n)
    {
    	vector<string> ret;
        if(n < 1)
            return ret;
        string temp;
        generateParenthesisCore(n, n,ret,temp);
        return ret;
    }
    void generateParenthesisCore(int l, int r,vector<string> &ret,string &temp)
    {
        if(l == 0 && r == 0)//说明左括号和右括号都用完了,即到达末尾了
        {
            ret.push_back(temp);
            return;
        }
        else
        {   //说明还没有到达末尾

        	//思考当前位置可以放置的所有合法值进行递归遍历
            if(l > 0)//思考什么时候此位置可以放置左括号
            {
            	temp.push_back('(');
            	generateParenthesisCore(l - 1, r,ret,temp);
            	temp.pop_back();

            }

            if(r > l)//思考什么时候此位置可以放置右括号
            {//(当此位置前的左括号多于右括号时,也就是它前面有左括号能抵消这个放置的右括号)
            	temp.push_back(')');
                generateParenthesisCore(l, r - 1,ret,temp);
                temp.pop_back();

            }

        }
    }
};

posted on 2021-05-05 22:45  朴素贝叶斯  阅读(91)  评论(0编辑  收藏  举报

导航