[LeetCode] 22. 括号生成

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

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

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

提示:
1 <= n <= 8

image.png

class Solution {
    List<String> ans = new ArrayList();
    int num;
    public List<String> generateParenthesis(int n) {
        num=n;
        String temp="";
        dfs(0,0,temp);
        return ans;
    }
    public void dfs(int lc,int rc,String temp){
        if(lc>=num && rc>=num ){
            ans.add(temp);
            return;
        }
        if(lc<num) dfs(lc+1,rc,temp+"(");
        if(rc<lc)  dfs(lc,rc+1,temp+")"); 
    }
}

在这之前尝试了类似于动态规划的解法,失败了

这是错的,很明显这样的DP没考虑到重构性.如n=4可以用两个n=2排列组合.

class Solution {
    public List<String> generateParenthesis(int n) {
        List<String> model = new ArrayList();
        model.add("()");
        for(int i=2;i<=n;i++){
            List<String> temp = new ArrayList();
            for(String s : model){
                //并列添加
                String mds1 = "()"+ s;
                String mds2 = s + "()";
                if(mds1.equals(mds2)){
                    temp.add(mds1);
                }else {
                    temp.add(mds1);
                    temp.add(mds2);
                }
                //包含添加
                temp.add("("+s+")");
            }
            model=temp;
        }
        Collections.sort(model);
        return model;
    }
}

参考了别人的解法

思路:动态规划

定义状态:

dp[i] 是一个数组,表示由 i 对括号生成的所有组合。

状态转移:

对于 0 <= j <= i-1, k = i - 1 - j,将 dp[j] 中所有的组合与 dp[k] 中所有的组合分别取出来,一一合并。

合并的时候不能将 dp[j] 中每一种组合与 dp[k] 中每一种组合直接合并,因为那样有重复的情况,不利于排除。

例如:

当 j = 1, k = 2 时:

dp[j] = ['()'];
dp[k] = ['()()', '(())'];
如果直接组合,得到的结果为:[ '( ) ( ) ( ) ', ' ( ) ( ( ) ) ' ]。

当 j = 2, k = 1 时:

dp[j] = ['()()', '(())'];
dp[k] = ['()']
如果直接组合,得到的结果为:[ ' ( ) ( ) ( ) ', ' ( ( ) ) ( ) ' ]。

此时会出现重复的情况:'()()()'。

而应该用一对括号将 dp[j] 中每一种组合括起来,并把 dp[k] 中每一种组合应该放到括号右边,这样就能保证合并之后每一种状态都是唯一的。

例如:

当 j = 1, k = 2 时:

dp[j] = ['()'];
dp[k] = ['()()', '(())'];
如果将 dp[j] 括起来再组合,得到的结果为:[ ' ( ( ) ) ( ) ( ) ', ' ( ( ) ) ( ( ) ) ' ]。

当 j = 2, k = 1 时:

dp[j] = ['()()', '(())'];
dp[k] = ['()'];
如果将 dp[j] 括起来再组合,得到的结果为:[ ' ( ( ) ( ) ) ( ) ', ' ( ( ( ) ) ) ( ) ' ]。

此时就没有重复的情况出现了。

初始状态:

dp[i] = [];
dp[0] = [''];
dp[1] = ['()'];
代码

/**
 * @param {number} n
 * @return {string[]}
 */
var generateParenthesis = function (n) {
  const dp = new Array(n + 1).fill(false).map(() => []);
  dp[0] = [''];
  dp[1] = ['()'];
  for(let i = 2; i <= n; i++) {
    for(let j = 0; j < i; j++) {
      let k = i - 1 - j;
      // dp[i] += dp[j] * dp[k];
      for(let jj = 0; jj < dp[j].length; jj++) {
        for(let kk = 0; kk < dp[k].length; kk++) {
          dp[i].push(`(${dp[j][jj]})${dp[k][kk]}`);
        }
      }
    }
  }
  // console.log(dp[n]);
  return dp[n];
};

// const n = 4
// generateParenthesis(n);

作者:20182726
链接:https://leetcode-cn.com/problems/generate-parentheses/solution/by-20182726-ci8b/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×