力扣22. 括号生成(动态规划)

力扣22. 括号生成(动态规划)

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

示例 1:

输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]
示例 2:

输入:n = 1
输出:["()"]

提示:

1 <= n <= 8

 

动态规划

反思:
首先,面向小白:什么是动态规划?在此题中,动态规划的思想类似于数学归纳法,当知道所有 i<n 的情况时,我们可以通过某种算法算出 i=n 的情况。
本题最核心的思想是,考虑 i=n 时相比 n-1 组括号增加的那一组括号的位置。

思路:

当我们清楚所有 i<n 时括号的可能生成排列后,对与 i=n 的情况,我们考虑整个括号排列中最左边的括号。
它一定是一个左括号,那么它可以和它对应的右括号组成一组完整的括号 "( )",我们认为这一组是相比 n-1 增加进来的括号。

那么,剩下 n-1 组括号有可能在哪呢?

【这里是重点,请着重理解】

剩下的括号要么在这一组新增的括号内部,要么在这一组新增括号的外部(右侧)。

既然知道了 i<n 的情况,那我们就可以对所有情况进行遍历:

"(" + 【i=p时所有括号的排列组合】 + ")" + 【i=q时所有括号的排列组合】

其中 p + q = n-1,且 p q 均为非负整数。

事实上,当上述 p 从 0 取到 n-1,q 从 n-1 取到 0 后,所有情况就遍历完了。

注:上述遍历是没有重复情况出现的,即当 (p1,q1)≠(p2,q2) 时,按上述方式取的括号组合一定不同。

第一个循环i是动态规划向下求解

第二个循环j是得到dp[i]之前(dp[0]----dp[i-1])的全部组合情况,作为索引

第三个循环p是得到dp[j]的全部组合情况

第四个循环q是得到dp[i-j-1]的全部组合情况

 

#include <iostream>
#include<vector>
using namespace std;

class Solution {
public:
    vector<string> generateParenthesis(int n) {
        if (n == 0)return {""};
        if (n == 1)return { "()" };
        vector<vector<string>>dp(n+1);//二维数组dp[n]代表括号对数时的有效组合
        dp[0] = { "" };//初始化条件
        dp[1] = { "()" };//初始化条件
        for (int i = 2; i <= n; i++)//开始计算i组括号时的括号组合
        {
            for (int j = 0; j < i; j++)//  开始遍历 p q ,其中p+q=i-1 , j 作为索引
            {
                for (int m = 0; m < dp[j].size(); m++)// p = j 时的括号组合情况
                {
                    string p = dp[j][m];
                    for (int k = 0; k < dp[i - j - 1].size(); k++)// q = (i-1) - j 时的括号组合情况
                    {
                        string q = dp[i - j - 1][k];
                        string str = "(" + p + ")" + q;
                        dp[i].push_back(str);
                    }
                }
            }
        }
        return dp[n];
    }
};
int main()
{
    Solution s;
    auto result = s.generateParenthesis(4);
    for (int i = 0; i < result.size(); i++)
    {
        cout << result[i] << " ";
    }
    cout << endl;
    std::cout << "Hello World!\n";
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值