[路飞]不同的二叉搜索树ii

92 阅读2分钟

记录 1 道算法题

不同的二叉搜索树ii

leetcode-cn.com/problems/un…


要求: 给一个数 n,返回节点值由 1 到 n 组成的各种二叉搜索树。放在数组中返回。

二叉树的个数正好符合卡特兰数,G(0) = 1, G(1) = 1, G(n) = G(i - 1) * G(n - i) 。也是一种递归的结果。搜索二叉树我们知道特点是左边的节点小于根节点,右边的节点大于根节点。所以对以任意的一个数作为根节点都可以将他比他小的树作为他的左边的子节点,比他大的数都可以作为右子节点。

比如: [1,2] 3 [4, 5] 其中 3 为根节点。(二叉搜索树的一个特点:中序遍历可以得到一个升序的数组,虽然这题用不上)

再比如: [1] 2 以 2 为根节点且 n = 2 时,得到的树,刚好是以 3 为根节点的树的一部分。就像卡特兰数、斐波那契数列的累进,n 的二叉搜索树也可以根据 n - 1, n - 2 ... 的树从底下一个组合上去。尽管每个数作为根节点,随着 n 的增大,子树的结构也越来越深,但总是一点点拼凑起来的。

所以我们要用递归进行解决,这种做法也叫回溯。

    function generateTrees(n) {
        if (n === 1) return [new TreeNode(1)]
        
        return generate(1, n)
    }
    
    function generate(start, end) {
        if (start > end) {
            return [new TreeNode(null)]
        }
        
        let res = []
        // start 到 end 个数,轮流当根节点的情况,例如 1 到 3
        for(let i = start; i <= end; i++) {
            // 递归计算子树的结构, 多种情况,要一一组合起来
            // 递归直到 叶子节点 和 1,即无法再拆分左右节点
            const left = generate(1, i - 1)
            const right = generate(i + 1, n)
            for(let j = 0; j < left.length; j++) {
                for(let k = 0; k < left.length; k++) {
                    res.push(new TreeNode(i, left[j], right[k]))
                }
            }
        }
        
        return res
    }