算法--括号生成(二叉树,回溯,深度优先)

195 阅读2分钟

leetcode 原题目:

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

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

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

题目理解起来是比较简单的,

深度优先遍历DFS 与树的先序遍历比较类似。 假设初始状态是图中所有顶点均未被访问,则从某个顶点出发,首先访问该顶点然后依次从它的各个未被访问的邻接点出发深度优先搜索遍历图,直至所有有路径相通的顶点都被访问到。若此时尚有其他顶点未被访问到,则另选一个未被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。

n=2 为 🌰 :

  • 先左括号一定是要多余右括号的,否则就不是一个有效的括号组合

用二叉树画出来就非常好理解深度优先遍历和回溯的过程:

image.png


/**
 * @param {number} n
 * @return {string[]}
 */
var generateParenthesis = function(n) {
    let res = []   // 目标结果
    let str = ''   // 符合条件的括号组合字符串
    dfs(res, str, 0, 0, n)     // 遍历
    return res        
};

var dfs = function(res, str, left, right, n) {
    if(str.length == n*2) {       // 所有括号都已经加入,就是我们想要的一种目标
        res.push(str)    // 将结果放入result
        return
    }
    if(left < right) return  // 左括号必须大于等于右括号的数量
    if(left < n) {      // 这是一个深度优先,也就是上图中二叉树不断向下访问直到末端的的过程
        str+='('    // 加入左括号
        dfs(res, str, left+1, right, n)
        str = str.substring(0, str.length-1)   // 回溯操作,当访问到树末端后需要向上回溯 去寻找其他的分支
    }
    if(right < n) {   // 同上面的加左括号的操作,这是一个向字符串中加入右括号的操作
        str+=')'
        dfs(res, str, left, right+1, n)  
        str = str.substring(0, str.length-1)
    }
}