题目描述:给定一个整数 n,生成所有由 1 ... n 为节点所组成的 二叉搜索树 。

示例如下:

  

  分析:这一题需要对比LeetCode96题来分析:https://www.cnblogs.com/KongJetLin/p/13054624.html

  第96题也是求所有由 1 ... n 为节点所组成的 二叉搜索树,但是96题返回的是所有二叉搜索树的数量,因此对于96题,我们只需要使用动态规划的方法,从n=2开始,根据:dp[n] = dp[0] * dp[n-1] + dp[1] * dp[n-2] + ...... + dp[i-1]*dp[n-i] + ...... + dp[n-2] * dp[1] + dp[n-1] * dp[0] 公式,逐个求dp[i] (i = 0,1,...,n),直到找到 dp[n] ,就是所有可能结构的二叉搜索树的数量。

  但是这一题95题,返回的是所有可能的二叉搜索树的根结点的集合 List<TreeNode>,我们可以使用递归的思想进行求解。

  求 1...n 的所有可能的二叉搜索树,可以分解为:

1)把 1 作为根节点,[ ] 空作为左子树,[ 2 ... n ] 的所有可能结构作为右子树;

2)2 作为根节点,[ 1 ] 作为左子树,[ 3...n ] 的所有可能结构作为右子树;

3)3 作为根节点,[ 1 2 ] 的所有可能作为左子树,[ 4 ... n ] 的所有可能作为右子树,然后左子树和右子树以3作为根结点进行两两组合。

...

3)n 作为根节点,[ 1... n ] 的所有可能作为左子树,[ ] 作为右子树。 

  对于求 [ 2 ... n ] 、 [ 3 ... n ] 、[ 1 2 ]等情况的所有可能,也可以利用上边的方法,把每个数字作为根节点,然后把所有可能的左子树和右子树组合起来即可。

  特殊情况,遇到 [ ] ,说明当前结点为null,以当前结点为根的所有可能子树只有一个,那就是 null,直接返回null;遇到 [ 1 ] 等只有一个数字的情况,当前结点为该数字,且当前结点的左右子树都没有结点(为null),那么以当前结点为根的所有可能子树只有一个,那就是当前数字,把该数字作为一棵树返回。

  详细的过程见下面代码分析:

public ArrayList<TreeNode> generateTrees (int n)
{
ArrayList<TreeNode> res = new ArrayList<>(); /*
当 n=0 的时候,不返回null,而是直接返回空的ArrayList<TreeNode>。
因为题目要求返回类型是ArrayList<TreeNode>,返回null会出错
*/
if(n == 0)
return res;
//查找 1 - n的数字所组成的所有可能结构的二叉树
return generateTrees(1, n);
} //查找 start到end 数字所组成的所有可能结构的二叉树,并将这些二叉树的根放入ArrayList<TreeNode>
private ArrayList<TreeNode> generateTrees(int start , int end)
{
//这个集合用于存储所有可能结构的二叉树的根(因为可能的二叉树结构有多个,因此要用ArrayList保存这些二叉树的根结点)
ArrayList<TreeNode> res = new ArrayList<>(); /*
可能遇到 start>end 的情况,如上一层递归以start为根,其左子树为generateTrees(start, start - 1),
即左子树没有结点,为null,那么所有可能的二叉树只有一个:null;
可能遇到 start=end 的情况,即已经找到最大树的叶子结点,叶子结点没有左右子树,
那么所有可能的二叉树只有一个:start/end 为根。 上述情况分别对应1结点的左子树(null)以及右子树(2)的情况。
1
/ \
null 2
*/
if(start > end)
{
res.add(null);
return res;//注意返回集合,因为上一层的递归遍历的是所有可能的二叉子树的根结点的集合
}
if(start == end)
{
res.add(new TreeNode(start));
return res;
} //第一个for循环用于遍历 start到end 之间所有的数字,求以这些数字为根的二叉树
for (int i = start; i <= end ; i++)
{
//求 start到i-1 数字组成的所有可能的二叉树,将这些二叉树根的集合返回,这些二叉树是以i为根的树的左子树
ArrayList<TreeNode> leftTrees = generateTrees(start, i - 1);
ArrayList<TreeNode> rightTrees = generateTrees(i + 1, end);//类似于求左子树的操作 /**
leftTrees 与 rightTrees分别存储所有可能的左子树与右子树的根结点。
我们需要将这些左子树与右子树两两组合,并将i作为当前树的根,连接这些左右子树,最后将这个根i添加到 res。 以i为根的树可能有多种结构,而我们通过最外层的循环,找到以 i=start-end 为根的所有可能树的结构,
将这些结构的根添加到 res 集合中,返回给上一层的递归即可。
*/
for (TreeNode leftTree : leftTrees)
{
for (TreeNode rightTree : rightTrees)
{
TreeNode root = new TreeNode(i);//以i作为根结点
//根结点连接所有可能的左右子树,i根结点若连接不同的左右子树,最后测试的时候代表其是不同的二叉树
root.left = leftTree;
root.right = rightTree;
//将这个结构的二叉搜索树的根添加到 res
res.add(root);
}
}
}
//出循环的时候,将以 i=start-end 为根的所有可能树的结构的根结点添加到 res,将res集合返回给上一层递归
return res; /**
注意,这里的返回值是ArrayList<TreeNode>,而不是 ArrayList<ArrayList<TreeNode>>,
因此我们需要查找每一个i(i=1,2,...,n)为根的所有可能的二叉树结构,并将这些根(i)结点添加到ArrayList<TreeNode>。 如果返回 ArrayList<ArrayList<TreeNode>>,就要找到所有可能的二叉树的所有结点的集合,将这些ArrayList<TreeNode>
再次封装到 ArrayList 中。
*/
}

95题--不同的二叉搜索树II(java、中等难度)的更多相关文章

  1. 96题--不同的二叉搜索树(java、中等难度)

    题目描述:给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种? 示例如下: 分析:本题可用动态规划的方法求解. 设 dp[n] 表示以 1 ... n 为节点组成的二叉搜索树的种类 ...

  2. 95. 不同的二叉搜索树 II

    95. 不同的二叉搜索树 II 题意 给定一个整数 n,生成所有由 1 ... n 为节点所组成的二叉搜索树. 解题思路 这道题目是基于不同的二叉搜索树进行改进的: 对于连续整数序列[left, ri ...

  3. Java实现 LeetCode 95 不同的二叉搜索树 II(二)

    95. 不同的二叉搜索树 II 给定一个整数 n,生成所有由 1 - n 为节点所组成的二叉搜索树. 示例: 输入: 3 输出: [ [1,null,3,2], [3,2,null,1], [3,1, ...

  4. LeetCode 95 | 构造出所有二叉搜索树

    今天是LeetCode专题第61篇文章,我们一起来看的是LeetCode95题,Unique Binary Search Trees II(不同的二叉搜索树II). 这道题的官方难度是Medium,点 ...

  5. 不同的二叉搜索树&II

    不同的二叉搜索树 只要求个数,递推根节点分割左右子树即可 class Solution { public int numTrees(int n) { int []dp=new int[n+1]; fo ...

  6. LeetCode-095-不同的二叉搜索树 II

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

  7. [LeetCode] 95. Unique Binary Search Trees II 唯一二叉搜索树 II

    Given n, generate all structurally unique BST's (binary search trees) that store values 1...n. For e ...

  8. LeetCode(95): 不同的二叉搜索树 II

    Medium! 题目描述: 给定一个整数 n,生成所有由 1 ... n 为节点所组成的二叉搜索树. 示例: 输入: 3 输出: [   [1,null,3,2],   [3,2,null,1],   ...

  9. LeetCode 95——不同的二叉搜索树 II

    1. 题目 2. 解答 以 \(1, 2, \cdots, n\) 构建二叉搜索树,其中,任意数字都可以作为根节点来构建二叉搜索树.当我们将某一个数字作为根节点后,其左边数据将构建为左子树,右边数据将 ...

随机推荐

  1. 这道LeetCode题究竟有什么坑点,让它的反对是点赞的9倍?

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是LeetCode专题的第38篇文章,我们一起来看看第65题,Valid Number. 曾经我们聊到过算法当中的一个类别--模拟题.所 ...

  2. k8s搭建实操记录一(master)

    #1)关闭CentOS7自带的防火墙服务 systemctl disable firewalld systemctl stop firewalld swapoff  -a     ##虚拟机要关闭交换 ...

  3. 前端Json对象与Json字符串互转(4种转换方式)

    1>jQuery插件支持的转换方式: $.parseJSON( jsonstr ); //jQuery.parseJSON(jsonstr),可以将json字符串转换成json对象 2>浏 ...

  4. 蒲公英 · JELLY技术周刊 Vol.08 -- 技术周刊 · npm install -g typescript@3.9.3

    登高远眺 沧海拾遗,积跬步以至千里 基础技术 官宣: Typescript 3.9 正式发布 TypeScript 3.9 正式发布,这个版本主要聚焦于性能.改进某些特性和提升稳定性.编译器效率在这一 ...

  5. 整理总结数据库常用sql语句,建议收藏,忘记了可以来看一下

    第一节课:sql语言介绍(参照PPT)及基本查询sql学习 1.数据库表的介绍 emp表:员工表 dept表:部门表 salgrady:薪资水平表 Balance: 2.基本的查询语句: 知识点: s ...

  6. Maven快速入门(二)手动创建maven项目hellomaven

    之前讲过Maven介绍及环境搭建,介绍了maven的作用和如何搭建maven环境.接下来就以一个helloworld的例子来说一说如何创建maven项目以及maven项目的项目结构,最后讲maven如 ...

  7. 面试官,别问我DNS了,也就这些!

    提到网络,基本上都能把DNS给扯上去.为啥呢,今天我们来一探究竟. 1 Chrome浏览器原理 还记得面试过程中被问了千百遍的"输入URL后发生了什么"这个经典问题吗,因为这个问题 ...

  8. 泛微 e-cology OA 前台SQL注入漏洞

    0x00概述 该漏洞是由于OA系统的WorkflowCenterTreeData接口在收到用户输入的时候未进行安全过滤,oracle数据库传入恶意SQL语句,导致SQL漏洞. 0x01影响范围 使用o ...

  9. Netty学习笔记(二) - ChannelPipeline和ChannelHandler

    ChannelPipeline 和 ChannelHandler 是 Netty 重要的组件之一,通过这篇文章,重点了解这些组件是如何驱动数据流动和处理的. 一.ChannelHandler 在上一篇 ...

  10. [01]HTML基础之简单介绍

    1.前言 现如今科技进步,足不出户尽晓天下事,一转身便仿若隔世茫然.科技绽放时代,网络技术对人们的触变无疑是深远而重大的,隐于缤纷绚丽的网页背后,是前端的蜕变更新. 如今,随意点开页面,绚丽华彩的特效 ...