【算法 -- LeetCode】(022) 括号生成

在这里插入图片描述

1、题目

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

示例 1:

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

示例 2:

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

题目链接:https://leetcode.cn/problems/generate-parentheses

2、图解

第 1 步:定义状态 dp[i]

使用 i 对括号能够生成的组合。

注意:每一个状态都是列表的形式。

第 2 步:状态转移方程:

  • i 对括号的一个组合,在 i - 1 对括号的基础上得到;
  • i 对括号的一个组合,一定以左括号 “(” 开始(不一定以 “)” 结尾),为此,我们可以枚举右括号 “)” 的位置,得到所有的组合;
  • 枚举的方式就是枚举左括号 “(” 和右括号 “)” 中间可能的合法的括号对数,而剩下的合法的括号对数在与第一个左括号 “(” 配对的右括号 “)” 的后面,这就用到了以前的状态。

状态转移方程是:

dp[i] = "(" + dp[可能的括号对数] + ")" + dp[剩下的括号对数]

  • “可能的括号对数” 与 “剩下的括号对数” 之和得为 i,故“可能的括号对数” j 可以从 0 开始,最多不能超过 i, 即 i – 1;
  • “剩下的括号对数” + j = i – 1,故 “剩下的括号对数” = i – j – 1。
    整理得:

dp[i] = "(" + dp[j] + ")" + dp[i- j - 1] , j = 0, 1, ..., i - 1

第 3 步:思考初始状态和输出

初始状态:因为我们需要 0 对括号这种状态,因此状态数组 dp 从 0 开始,0 个括号当然就是 [“”]。
输出:dp[n] 。
这个方法暂且就叫它动态规划,这么用也是很神奇的,它有下面两个特点:

1、自底向上:从小规模问题开始,逐渐得到大规模问题的解集;

2、无后效性:后面的结果的得到,不会影响到前面的结果。

3、Java 示例代码

class Solution {
    
    
    public List<String> generateParenthesis(int n) {
    
    
        if (n == 0) {
    
    
            return new ArrayList<>();
        }
        // 这里 dp 数组我们把它变成列表的样子,方便调用而已
        List<List<String>> dp = new ArrayList<>(n);

        List<String> dp0 = new ArrayList<>();
        dp0.add("");
        dp.add(dp0);

        for (int i = 1; i <= n; i++) {
    
    
            List<String> cur = new ArrayList<>();
            for (int j = 0; j < i; j++) {
    
    
                List<String> str1 = dp.get(j);
                List<String> str2 = dp.get(i - 1 - j);
                for (String s1 : str1) {
    
    
                    for (String s2 : str2) {
    
    
                        // 枚举右括号的位置
                        cur.add("(" + s1 + ")" + s2);
                    }
                }
            }
            dp.add(cur);
        }
        return dp.get(n);
    }
}

执行结果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/duoduo_11011/article/details/131795479