题目:
数字 n
代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
示例1:
输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]示例2:
输入:n = 1
输出:["()"]
解题思路:
采用动态规划算法:
1.当i=n时,括号的组合是:
2."(" + 【i=p时所有括号的排列组合】 + ")" + 【i=q时所有括号的排列组合】
3.其中p+q=n-1
4.当p从0遍历到n-1,q从n-1遍历到0后,那么所有情况已经全部遍历过了
vector<string> generateParenthesis(int n) {vector<vector<string>> dp(n+1);//这里要初始化dp的大小为n+1,因为有个dp[0]是空字符串,保证了下标与n是相同的dp[0] = { "" };dp[1] = { "()" };if(n==0||n==1) return dp[n];//当n=0,或n=1时,直接返回dp[n]即可for (int i = 2; i <= n; i++) {for (int j = 0; j <i; j++) {for (string p : dp[j])//这里是c++11的用法,相当于遍历dp[j]中所有的字符串for (string q : dp[i - j - 1]) {string str = "(" + p + ")" + q;dp[i].push_back(str);//每遍历一次,就存放一次结果到dp[i]中}}}return dp[n];}
采用递归回溯来实现:
1.左括号和右括号的数量不能超过n
2.每放置一个左括号,才可以放置右括号,(右括号不能先于左括号)
递归条件
1.左括号个数要大于右括号个数,才能继续递归
注意:
1.最终结果 vector<string> ret;
2.临时结果 string temp;
void fn(string temp, int left, int right, vector<string>& ret)
{if (left == 0 && right == 0){ret.push_back(temp);return;}if (left > 0)//左括号只要还有存量,就可以放fn(temp + '(', left - 1, right, ret);if (right > left)//左括号剩的比右括号少fn(temp + ')', left, right - 1, ret);}