22. 括号生成

一、题目

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

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

二、题解

1.思路

没有花里胡哨的操作,直接深度穷举全部出来,不过效率不高做了一些重复工作。

2.代码

第一版未优化代码
class Solution {
public:
vector<string> ans;
//leftk代表目前左括号能剩余的数量
//rightk代表目前右括号还剩余的数量
//totalk代表当前左右括号还剩余的数量
void fun(int leftk,int rightk,int totalk,string tempans){
	//totalk为0说明已经搜索到一种组合
	if(totalk==0)ans.push_back(tempans);
	else{
		//当左括号已经添加的数量比右括号数量多的时候才可以加左括号和右括号
		//也即是左括号剩余的少,右括号剩余的多
		if(leftk<=rightk){
		//左括号没用完,可以加左括号也可以加右括号
			if(leftk!=0){
				//加左括号 
				fun(leftk-1,rightk,totalk-1,tempans+("(")); 
				//加右括号 
				fun(leftk,rightk-1,totalk-1,tempans+(")"));
			}
			//左括号加完了,只剩由括号,直接将右括号全加上去
			else{
				for(int i=0;i<rightk;i++){
					tempans.append(")");
				}
				//左括号加完右括号也加完,说明搜索到一种答案
			ans.push_back(tempans);
			}
		}
	}
}
    vector<string> generateParenthesis(int n) {
        fun(n,n,2*n,"");
        return ans;
    }
};

3.优化

在执行过程中会左重复工作
可以使用备忘录优化
当成对的括号匹配成功后,剩余的括号可以不用再搜索了。
在这里插入图片描述

class Solution {
public:
vector<string> ans[9];
void fun(int i,int leftk,int rightk,int totalk,string tempans){
//leftk=rightk说明已经目前的括号字符串tempans全是成对的括号,
//剩下的leftk个成对的括号之前已经得到了可以直接使用
	if(leftk==rightk&&leftk!=i){
		int x=leftk;
		int len=ans[x].size();
		for(int v=0;v<len;v++){
			ans[i].push_back(tempans+ans[x][v]);
		}
		return;
	}else{
		if(totalk==0){
		ans[i].push_back(tempans);
		}
		else{
			if(leftk<=rightk){
				if(leftk!=0){
					//加左括号 
					fun(i,leftk-1,rightk,totalk-1,tempans+("(")); 
				
					//加右括号 
					fun(i,leftk,rightk-1,totalk-1,tempans+(")"));
				
				}else{
					for(int i=0;i<rightk;i++){
						tempans.append(")");
					}
				ans[i].push_back(tempans);
				}
			}
		}
	}
	
}
    vector<string> generateParenthesis(int n) {
        ans[0].push_back("");
        ans[1].push_back("()");
        if(n==1)return ans[n];
	    for(int i=2;i<=n;i++){
		     fun(i,i,i,2*i,"");
	    }
        return ans[n];
    }
};

即使优化其基本思想依旧是暴力搜索。

可以换一种思路:n个括号组成的字符串中,我们总是拿出最左边的: “(” ,找到其对应的: “)” 。

那么剩下的n-1个括号在哪?

答案是只能在这个括号的里面和右边,因为我们找到的这个括号是最左的
即:( j对括号 )n-1-j对括号

class Solution {
public:
    vector<string> generateParenthesis(int n) {
        vector<string> ans[n+1];
        ans[0].push_back("");
        ans[1].push_back("()");
        if(n==1)return ans[n];
        //计算i对括号的情况
        for(int i=2;i<=n;i++){
        
            for(int j=0;j<i;j++){
            //括号里面
                for(string str1 : ans[j]){
                //括号右边
                    for(string str2 : ans[i-j-1]){
                        ans[i].push_back("("+str1+")"+str2);
                    }
                }
            }
        }
        return ans[n];
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值