「这是我参与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
。
而对于 2
和 3
来说,它两也需要保证具有二叉树的性质 左子树值小于根节点,右子树节点的值大于根节点
。则一定只有下面两种组成子树的方式:
最后我们再将根节点为 1
的左孩子和它的两个右孩子做组合,只能有如下的两种结果:
综上所述,大致的步骤如下所示:
- 先选择一个根节点
x
- 根据左孩子上面的元素
1 ~ x-1
,组成所有可能的子树 - 根据右孩子上面的元素
x+1 ~ n
,组成所有可能的子树 - 将得到的左孩子和右孩子组合,返回结果即可
二、实现
实现代码
实现代码与思路中保持一致
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);
}
复制代码
结果
三、总结
感谢看到最后,非常荣幸能够帮助到你~♥
如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~