22. 括号生成【中等】

leetcode:https://leetcode-cn.com/problems/generate-parentheses/

方法一:

动态规划

n:代表有n对括号

ans[i]:代表一共 i 对括号形成的所有组合

我们要求的是ans[n]

我们知道对于第n对括号是由一个左括号和一个右括号组成,而且无论多少对括号组成的排列的最左边一定是左括号

然后对于n对括号形成的组合中,剩下n-1对括号要么是在第n对括号中间,要么在第n对括号右边

所以假设我们知道1到 n - 1 括号形成的所有组合ans[1]到ans[n - 1],则对于n对括号组成的所有组合,无非就是

( + ans[q] + ) + ans[r]

我们知道ans[1] = ['()']

所以ans[2]的所有组合就是

( + ans[0] + ) + ans[1]

( + ans[1] + ) + ans[0]

这样就可以得到ans[1]和ans[2],利用之前计算的结果,然后依次递推可以计算出ans[3]、ans[4]。。。ans[n]

/**
 * @param {number} n
 * @return {string[]}
 */
var generateParenthesis = function(n) {
    // 第1组组合只有一种
    let ans = [[],['()']];
    // 还需要在原来基础上还需要增加i组括号
    for (let i = 2; i <= n; i++) {
        ans[i] = [];
        let temp = [];
        // 遍历组合ans[j]和 ans[i - j]形成的所有组合
        for (let j = 0; j < i; j++) {
            const qArr = ans[j];
            const rArr = ans[i - j - 1];
            // 右边没有
            if (qArr.length === 0) {
                for (let r = 0, rLen = rArr.length; r < rLen; r++) {
                    temp.push('()' + rArr[r]);
                }
                continue;
            }
            // 中间没有
            if (rArr.length === 0) {
                for (let q = 0,qLen = qArr.length; q < qLen; q++) {
                    temp.push('(' + qArr[q] + ')')
                }
                continue;
            }
            // 中间和右边都有
            for (let q = 0,qLen = qArr.length; q < qLen; q++) {
                for (let r = 0, rLen = rArr.length; r < rLen; r++) {
                    temp.push('(' + qArr[q] + ')' + rArr[r]);
                }
            }
        }
        ans[i] = temp;
        console.log(`ans[${i}]`, ans[i])
    }  
    return ans[n];
};

方法二:

深搜dfs + 剪枝

其实就是插入n次括号,每次有两种选择,左括号或者右括号,可以当做一个二叉树

边界:左右括都已经插入n个了,即形成要求的一组组合

不符合条件的:插入左括号或者右括号超过n个,或者右括号数量超过左括号,对于二叉树遍历过程中遇到这样的不再继续遍历,也就是【剪枝】

/**
 * @param {number} n
 * @return {string[]}
 */
var generateParenthesis = function(n) {
    let arr = [];
    // 二叉树深搜    
    const dfs = function (arr, str, l, r, n) {
        // 不符合组合条件的不再递归【剪枝】    
        if (l > n || r > n || r > l) return;
        if (l === n && r === n) {
            arr.push(str);
            return;
        }
        // 加左括号
        dfs(arr, str + '(', l + 1, r, n);
        // 加右括号
        dfs(arr, str + ')', l, r + 1, n);
    }
    dfs(arr, '', 0, 0, n);
    return arr;
};

-----smile

原文地址:https://www.cnblogs.com/Walker-lyl/p/14593133.html