leetcode #96 不同的二叉搜索树 | 刷题之路第二站——动态规划类问题

题号 96

题目描述

给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种?

示例:

输入: 3
输出: 5
解释:
给定 n = 3, 一共有 5 种不同结构的二叉搜索树:

   1         3     3      2      1
    \       /     /      / \      \
     3     2     1      1   3      2
    /     /       \                 \
   2     1         2                 3

链接:leetcode #96 不同的二叉搜索树

 

概念解释——二叉搜索树

Binary Search Tree——二叉搜索树、二叉查找树、二叉排序树等等

是指这样的一种二叉树:

1 - 要么是一棵空树;

2 - 要么:

如果根节点的左子树不空,则左子树上所有节点的值小于根节点的值;如果根节点的右子树不空,则右子树上所有节点的值大于根节点的值;且它的左、右子树也分别是二叉排序树。

举个栗子:

 

解题思路——动态规划

Step1、2:描述问题的最优解结构特征、递归定义最优解值

按照动态规划的解决思路来说,对于给定的整数 n,由 1 .. n 为节点组成的二叉搜索树的个数应该和 n - 1 个节点的二叉搜索树个数、n - 2 个节点的二叉搜索树个数、…… 、有关。

设立 v[ n ] 表示由 1 .. n 为节点组成的二叉搜索树的个数:

n = 0 时,二叉搜索树为空树,因此 v[ 0 ] = 1;

 

n = 1 时,二叉搜索树只包含一个节点

   O        
  / \     
左0 右0

 因此 v[ 1 ] = 1;

 

n = 2 时,去除一个根节点,剩下的一个节点可能是左子树,也可能是右子树,如下所示:

   O         O
  / \       / \
左0 右1   左1 右0

因为零节点的二叉树只有一种,一节点的二叉搜索树也只有一种,

因此 v[ 2 ] = v[ 0 ] × v[ 1 ] + v[ 0 ] = 2

 

n = 3 时,去除一个根节点,剩下的两个节点的可能分布如下所示:

   O          O          O
  / \        / \        / \
左0 右2    左1 右1    左2 右0

又因为两节点的二叉查找树有两种,一节点的二叉搜索树有一种,

因此 v[ 3 ] = v[ 0 ] × v[ 2] + v[ 1 ] × v[ 1 ] + v[ 2 ] × v[ 0 ] = 5

 

n = 4 时,去除一个根节点,剩下的三个节点的可能分布如下所示:

   O          O          O          O
  / \        / \        / \        / \
左0 右3    左1 右2    左2 右1    左3 右0

因此 v[ 4 ] = v[ 0 ] × v[ 3 ] + v[ 1 ] × v[ 2] + v[ 2 ] × v[ 1] + v[ 3 ] × v[ 0] = 14

 

n = 5 时,去除一个根节点,剩下的四个节点可能分布如下所示:

   O          O          O          O          O
  / \        / \        / \        / \        / \
左0 右4    左1 右3    左2 右2    左3 右1     左4 右0

因此 v[ 5 ] = v[ 0 ] × v[ 4 ] + v[ 1 ] × v[ 3 ] + v[ 2 ] × v[ 2 ] + v[ 3 ] × v[1 ] + v[ 4 ] × v[ 0 ] = 42

 

 ……

 

对于 整数 n ,去除一个根节点,剩下的 n - 1 个节点可能分布如下所示:

   O          O          O          O               O          O
  / \        / \        / \        / \     ……      / \        / \
左0 右n-1  左1 右n-2  左2 右n-3  左3 右n-4      左n-2 右1  左n-1 右0

因此 v[ n ] = v[ 0 ] × v[ n - 1 ] + v[ 1 ] × v[ n - 2 ] + v[ 2 ] × v[ n - 3] + …… + v[ n - 2 ] × v[ 1 ] + v[ n - 1 ] × v[ 0 ]

此问题的底是 v[ 0 ] = 1。

 

Step3、4:自底向上计算最优解值、输出最优解值

依次计算 v[ 1 ] 、v[ 2 ] 、…… v[ n ],问题的解就是终点 v[ n ]  的值。

代码实现如下:

class Solution {
public:
	int numTrees(int n) {
		vector<int> v(n+1);    //数组v用于存放以各整数为节点的二叉搜索树的个数
		v[0] = 1;    //问题的底
		for (int i = 1; i <= n; i++) {    //依次计算v[1] v[2] …… v[n]的值
			for (int j = 0; j <= i-1; j++) {
				v[i] += v[j] * v[i - (j + 1)];
			}
		}
		return v[n];
	}
};

时间复杂度:O( n ) 

空间复杂度:O( n ) 

 

计算二叉搜索树个数的公式:

对于具有 n 个节点的二叉搜索树而言,其可能的不同种类的二叉搜索的树的个数为:

 v[ n ] = \frac{C(n, 2n)}{n + 1}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值