力扣第九十五题-不同的二叉搜索树 II

「这是我参与11月更文挑战的第16天,活动详情查看:2021最后一次更文挑战

前言

力扣第九十五题 不同的二叉搜索树 II 如下所示:

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

示例 1:

输入: n = 3
输出: [[1,null,2,null,3],[1,null,3,2],[2,1,3],[3,1,null,null,2],[3,2,null,1]]
复制代码

一、思路

题目意思很简单,就是需要我们返回所有不同的从 1 ~ n 组成的二叉搜索树

那么什么是 二叉搜索树 呢? 它的定义如下所示:

二叉搜索树(Binary Search Tree)可能是一棵空树,或者是具有下列性质的二叉树:

  • 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值
  • 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值

其实二叉搜索树的定义是没必要特意去记的,因为 二叉搜索树 它的作用就是用于快速搜素的。举个例子:我们如果发现根节点的值小于目标值,则可以直接去右孩子上检索。

我们可以先选一个根节点,这样左孩子和右孩子的元素都确定了。例如对于 n = 3 来说,假设我们选择了 1 作为根节点。

则左孩子一定为 null,而右孩子的元素一定为 2 和 3

而对于 23 来说,它两也需要保证具有二叉树的性质 左子树值小于根节点,右子树节点的值大于根节点。则一定只有下面两种组成子树的方式:

image.png

最后我们再将根节点为 1 的左孩子和它的两个右孩子做组合,只能有如下的两种结果:

image.png

综上所述,大致的步骤如下所示:

  1. 先选择一个根节点 x
  2. 根据左孩子上面的元素 1 ~ x-1,组成所有可能的子树
  3. 根据右孩子上面的元素 x+1 ~ n,组成所有可能的子树
  4. 将得到的左孩子和右孩子组合,返回结果即可

二、实现

实现代码

实现代码与思路中保持一致

public List<TreeNode> generateTrees(int n) {
    if (n == 0) {
        return new LinkedList<>();
    }
    return dfs(1, n);
}

public List<TreeNode> dfs(int start, int end) {
    List<TreeNode> ret = new LinkedList<>();
    if (start > end) {
        ret.add(null);
        return ret;
    }
    // 枚举可行根节点
    for (int i = start; i <= end; i++) {
        // 找到所有的左子树
        List<TreeNode> leftTrees = dfs(start, i - 1);

        // 找到所有的右子树
        List<TreeNode> rightTrees = dfs(i + 1, end);

        // 组合
        for (TreeNode left : leftTrees) {
            for (TreeNode right : rightTrees) {
                TreeNode currTree = new TreeNode(i);
                currTree.left = left;
                currTree.right = right;
                ret.add(currTree);
            }
        }
    }
    return ret;
}
复制代码

测试代码

public static void main(String[] args) {
    new Number95().generateTrees(3);
}
复制代码

结果

image.png

三、总结

感谢看到最后,非常荣幸能够帮助到你~♥

如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~

猜你喜欢

转载自juejin.im/post/7031143982675853349