LeetCode每日一题之“不同的二叉搜索树” 更新Go语言版本

题目:给定一个整数 n,求以 1 … n 为节点组成的二叉搜索树有多少种?
示例 :

输入: 3
输出: 5
解释:
给定 n = 3, 一共有 5 种不同结构的二叉搜索树:
在这里插入图片描述

这道题想让我们找出有多少不同的二叉搜索树,首先对于一个二叉树而言,左子叶小于其根,右子叶大于其根。
要找不同的树,最好的方法是从根入手,给定整数1到 n,那么其中每一个整数都可作为单独的根存在。
确定了最基础的根之后,剩下的数字重新排列,又可以每个数作为子树的新根,进而产生不同的树。
因此这道题的核心思想就是不断确定新的根,将一个大树一直细分为一个个小树去求解,这里我们可以利用动态规划去解决这个问题。

定义:
result [n] : 长度为 n 的序列,能够形成多少不同的二叉树
F[ i , n ] : 以 i 为根,序列长度为 n 的数字序列能够产生多少不同的二叉树(1 ≤ i ≤ n)

通过这两个定义的变量,我们可以得出一个新的关系式:
在这里插入图片描述
不难看出,长度为 n 的序列得出的不同二叉树总数量等于所有不同根能产生的不同二叉树数量总和。
然而对于F[i,n]来说,我们还可以将其拆分成其他形式。

想象一下,当数字 i 作为树的根部时,序列 1至 (i - 1)会成为这个树的左子树(因为它们都比 i 小),而序列(i - 1)至 n 会成为这个树的右子树(因为它们都比 i 大)。

假设左子树有 m 种不同情况,右子树有 n 种不同情况,通过排列组合,我们很自然的能得出,在根为 i 的情况下,总共有 m × n 种情况,根据之前对 result [ n ] 的定义,我们可以重写F[i,n]

F [ i , n ] = result [ i - 1 ] × result [ n - i ]

同时关于result [ n ] 的关系式也可以改变:
在这里插入图片描述
得出这个式子后,只要我们从头开始计算,最后就能得出想要的答案,不要忘记设置初始边界条件:

result [0] = 1 (序列长度是0,只有1种情况)
result [1] = 1 (序列长度是1,只有1种情况)

代码实现:

public class answer2 {
    public int numTrees(int n){
        int[] result = new int[n+1];
        int i = 0;
        int j = 0;
        result[0] = 1;//初始边界条件
        result[1] = 1;
        for(i = 2;i<=n;i++){
            for(j = 1;j<=i; j++){
                result[i] = result[i] + (result[j - 1])*(result[i - j]);
                //从头开始,反复迭代计算结果,要想计算出 i = n 时的值,必须先将之前的所有值算出
            }
        }
        return result[n];
    }
}

代码(Go):

func numTrees(n int) int {
	result := make([]int,n+1)
	i := 0
	j := 0
	result[0],result[1] = 1,1
	for i=2;i<=n;i++ {
		for j = 1;j<=i;j++ {
			result[i] = result[i] + result[j-1]*result[i-j]
		}
	}
	return result[0]
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值