算法日记---不同的二叉搜索树

题目

在这里插入图片描述

思考

分析: 选取i作为根节点 则   
			左子树分支为1:i-1
			右子树分支为i+1:n    亦即   1:n-i

故而问题可转化为: n个节点的树=(所有i)  i-1节点 * n-i节点  

在这里插入图片描述

具体

示例中 f(3)= f(0)*f(2)     +f(1)*f(1)    +f(2)*f(0)


易知:
		0个节点  f(0)=0
		1个节点  f(1)=1
		2个节点  f(2)=2


f(3)= 0*2    +   1*1 + 2*0    but   ---> 0:含义无子树  故   此时应另  f(0)=1


通用性: n个节点--->    确定第i个   剩余n-1个节点     左右两分支子问题  
 故可以通过   		  f(0)  f(1)  ===> f(2)     
 				      f(0)   f(1)  f(2)  ===> f(3)
 		       f(0)   f(1)  f(2)  f(3)  ===> f(4)
				....
				====> f(n)

算法实现

# -*- encoding: utf-8 -*-


def focution(n):
    f = [0] * (n + 1)
    f[0], f[1] = 1, 1

    for i in range(2, n + 1):
        for j in range(1, i + 1):
            f[i] += f[j - 1] * f[i - j]

    return f[n]


if __name__ == "__main__":
    param = input("节点数:")

    print("种类:", focution(int(param)))

    pass

类似问题: 跳台阶f(n)=f(n-1)+f(n-2)…

[1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796] 卡特兰数

卡特兰数

出入栈序列: C2nn / (n+1)

卡特兰数,又称卡塔兰数,是组合数学中一种常出现于各种计数问题中的数列。以比利时的数学家欧仁·查理·卡塔兰 (1814–1894)的名字来命名。1730年左右被蒙古族数学家明安图 (1692-1763)使用于对三角函数幂级数的推导而首次发现,1774年被发表在《割圜密率捷法》。 百度百科

明安图数,又称卡塔兰数,英文名Catalan number,是组合数学中一个常出现于各种计数问题中的数列。以中国蒙古族数学家明安图 (1692-1763)和比利时的数学家欧仁·查理·卡塔兰 (1814–1894)的名字来命名,其前几项为(从第零项开始) : 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796,… 百度百科

在这里插入图片描述

经典问题

  1. 进出栈序列
    我们将进栈表示为 +1,出栈表示为 -1,则 1 3 2 的出栈序列可以表示为:+1 -1 +1 +1 -1 -1。
    根据栈本身的特点,每次出栈的时候,必定之前有元素入栈, 即对于每个 -1 前面都有一个 +1 相对应。因此,出栈序列的 所有前缀和 必然大于等于 0,并且 +1 的数量 等于 -1 的数量。

    接下来让我们观察一下 n = 3 的一种出栈序列:+1 -1 -1 +1 -1 +1。序列前三项和小于 0,显然这是个非法的序列

    如果将 第一个 前缀和小于 0 的前缀,即前三项元素都进行取反,就会得到:-1 +1 +1 +1 -1 +1。此时有 3 + 1 个 +1 以及 3 - 1 个 -1

    因为这个小于 0 的前缀和必然是 -1,且 -1 比 +1 多一个,取反后,-1 比 +1 少一个,则 +1 变为 n + 1 个,且 -1 变为 n - 1 个。进一步推广,对于 n 元素的每种非法出栈序列,都会对应一个含有 n + 1 个 +1 以及 n - 1个 -1 的序列

    如何证明这两种序列是一一对应的?

    假设非法序列为 A,对应的序列为 B。每个 A 只有一个"第一个前缀和小于 0 的前缀",所以每个 A 只能产生一个 B。而每个 B 想要还原到 A,就需要找到"第一个前缀和大于 0 的前缀",显然 B 也只能产生一个 A。

    每个 B 都有 n + 1 个 +1 以及 n - 1 个 -1,因此 B 的数量为 C2nn+1,相当于在长度为 2n 的序列中找到n + 1个位置存放 +1。相应的,非法序列的数量也就等于 C2nn+1

    出栈序列的总数量共有 C2nn ,因此,合法的出栈序列的数量为 C2nn - C2nn+1

  2. 括号序列
    n 对括号,则有多少种 “括号匹配” 的括号序列
    左括号看成 +1,右括号看成 -1,那么就和上题的进出栈一样

  3. 满二叉树
    n + 1 个叶子节点能够构成多少种形状不同的(国际)满二叉树
    (国际)满二叉树定义:如果一棵二叉树的结点要么是叶子结点,要么它有两个子结点,这样的树就是满二叉树。
    使用深度优先搜索这个满二叉树,向左扩展时标记为 +1,向右扩展时标记为 -1。

    由于每个非叶子节点都有两个左右子节点,所有它必然会先向左扩展,再向右扩展。总体下来,左右扩展将会形成匹配,即变成进出栈的题型。
    n + 1个叶子结点会有 2n 次扩展.

  4. 凸变形三角划分
    在一个凸多边形中,通过若干条互不相交的对角线,把这个多边形划分成了若干个三角形。任务是键盘上输入凸多边形的边数n,求不同划分的方案数f(n)。比如当n=6时,f(6)=14。
    因为凸多边形的任意一条边必定属于某一个三角形,所以我们以某一条边为基准,以这条边的两个顶点为起点P1和终点Pn(P即Point),将该凸多边形的顶点依序标记为P1、P2、……、Pn,再在该凸多边形中找任意一个不属于这两个点的顶点Pk(2<=k<=n-1),来构成一个三角形,用这个三角形把一个凸多边形划分成两个凸多边形,其中一个凸多边形,是由P1,P2,……,Pk构成的凸k边形(顶点数即是边数),另一个凸多边形,是由Pk,Pk+1,……,Pn构成的凸n-k+1边形。ok … 二叉搜索树问题

  5. 电影购票
    电影票一张 50 coin,且售票厅没有 coin。m 个人各自持有 50 coin,n 个人各自持有 100 coin。

    则有多少种排队方式,可以让每个人都买到电影票。

电影购票

持有 50 coin 的人每次购票时不需要找零,并且可以帮助后面持有 100 coin 的人找零;而对于持有 100 coin 的人每次购票时需要找零,但 100 coin 对后面的找零没有任何作用。

因此,相当于每个持有 100 coin 的人都需要和一个持有 50 coin 的人进行匹配。我们将持有 50 coin 的标记为 +1,持有 100 coin 的标记为 -1,此时又回到了进出栈问题。

不同的是,m 并一定等于 n,且 排队序列是一种排列,需要考虑先后顺序 ,例如各自持有 50 coin 的甲和乙的前后关系会造成两种不同的排队序列。所以,将会有 在这里插入图片描述

第二项为什么是Cm+nm+1,其实很简单,我们每次把第一个前缀小于0 的前缀取反后,会造成 +1 多了一个而 -1 少了一个。这里 +1 有 m 个,-1 有 n 个,取反后 +1 变成m + 1个,-1 变成n - 1个,总和不变。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值