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

177 阅读1分钟

Offer 驾到,掘友接招!我正在参与2022春招系列活动春招打卡任务,点击查看活动详情

leetcode-95 不同的二叉搜索树II

题目介绍

给你一个整数 n ,请你生成并返回所有由 n 个节点组成且节点值从 1 到 n 互不相同的不同 二叉搜索树。可以按 任意顺序 返回答案。

示例1

image.png

输入:n = 3
输出:[[1,null,2,null,3],[1,null,3,2],[2,1,3],[3,1,null,null,2],[3,2,null,1]]

示例2

输入: n = 1
输出: [[1]]

提示:

  • 1 <= n <= 8

解题思路

这道题使用 递归 + 排列组合 的方式来求解,我们以一棵 3 个节点的树来进行讲解。

首先,一棵 3 个节点的二叉搜索树分别可以以 123 为根节点进行构建,根据二叉搜索树根节点一定比左节点大同时比右节点大的特点:

  1. 1 为根节点。左子树没有任何节点,是 [null],右子树的节点为 {2, 3},有两种情况 [2, null, 3][3, 2, null],因此以 1 为根节点的情况就是左子树和右子树的一种排列组合,数量为 2

1646572676(1).png

  1. 2 为根节点。因为左子树只有节点 1,右子树只有节点 3,因此左右子树的排列组合只有一种情况

1646572745(1).png

  1. 3 为根节点。因为 {1, 2} 为左子树的节点,有两种情况 [2, 1, null][1, null, 2],右子树没有节点,为 [null],左右子树的排列组合数量为 2

1646572911(1).png

因此以 3 个节点构成的二叉搜索树有 2 + 1 + 2 = 5 种情况。但是题目要求我们给出所有的情况,因此我们可以以当前节点为根节点,计算其左右子树的结构,然后构建一棵树

更多节点构成的二叉搜索树与 3 个节点构成二叉搜索树的情况类似,只是根节点的左右子树的可能结构需要以递归的方式来得出

解题代码

var generateTrees = function(n) {
    // n 个节点分别是 1 - n
    const ans = dfs(1, n)
    return ans
};

var dfs = function(l, r) {
    const ans = []
    
    // 说明当前的树不存在,没有节点,返回 null
    if (l > r) {
        ans.push(null)
        return ans
    }

    for (let i = l; i <= r; i++) {
        // 获得构成左子树的所有情况
        const left_tree = dfs(l, i - 1)
        // 获得构成右子树的所有情况
        const right_tree = dfs(i + 1, r)

        // 当前树的所有情况就是左子树和右子树之间的排列组合
        for (const left of left_tree) {
                for (const right of right_tree) {
                // 构建以当前节点为根节点,左子树和右子树随机组合的树
                ans.push(new TreeNode(i, left, right))
            }
        }
    }

    // 返回当前树的所有构建情况
    return ans
}