leetcode 96 不同的二叉搜索树: 同构问题分析 卡特兰数 Catalan Number

21 篇文章 1 订阅
6 篇文章 0 订阅

做动态规划的时候看到这道题 力扣 96 不同的二叉搜索树 然后就想起了之前学的一个 Catalan Number 的知识点。这里复习一下。


组合差形式定义 defined in form of difference of combinatorial numbers

特定01序列问题

考虑生成01序列, 其中对于第i位, I in range(len(seq)), 其前面的1必须多于等于0, 且最终count(0)==count(1)

此要求可以进行一个几何建模: 指定右上为1, 左下为0.

则有: x in (0,2n), f(0) = 0, 有 f(2n) = 0, 根据附加条件, 不能经过 y= -1 轴.

进行几何条件转换(如图,matplotlib 绘制):

 

然后考虑去掉经过 y= -1 轴的部分: 进行几何考虑, 对于出现经过 y = -1 直线的步骤来说, 其必须往回走(右上, 即1作为序列该位填充数) 至少一步才能回到0点, 如图进行翻转, 翻转后图形必经过-2且最终停止在-2.

这一部分怎么计算呢 ?

回忆上面的 2nn 是从2n 步骤里挑选 n步作为 1/0 的意思.

在翻转的前提下, 会到达 -2 为终点的走法总数是 2𝑛 选 n+1 or 2n 选 n−1 (这里用了转换思路, 通过求翻转版本的走法数等于经过-1的走法数 !)

更深刻的理解是: 每一种经过 -1 线的方案, 可以一一对应(映射)我们的翻转后的方案!

而翻转后的方案可以通过 2n 选 n+1 来计算!

从而得到第一个定义式:

 

对角边界的方块寻路问题

从原点出发,每次向x或y轴正方向移动1单位,到达点(n,n),且在移动过程中不越过第一象限平分线 (图中红线) 的移动方案数。

这里的分析过程和1 的如出一辙的. 不再重复分析: 指明粗红色为越界路线, 蓝色为其经过绿线(等价上一题的-1线)后的翻转路线, 同样是一个映射.

组合数学式的化简: (closing form solution)


递归定义

括号匹配问题

n对()括号有多少种合法形态?

how many legal styles of combination of n pair of brackets

A recursive solution:

def parenthesis(n):

    if n == 0:return 1

    def helper(count_left, count_right):

        if count_left == count_right == 0:

            return 1

        if count_left >= count_right or count_right == 0:

            return helper(count_left-1, count_right)

        if count_left ==0:

            return helper(count_left, count_right-1)

        if count_left < count_right:

            a = helper(count_left, count_right-1) +\

               helper(count_left-1, count_right)

            return a

    return helper(n,n)

考虑方法:

二叉树种类问题

先进行一个复习: n个叶子节点的 full binary tree 和 n个节点的二叉树是同构模型.

证明过程是: 满二叉树的每个节点都有2个子节点….算了, 回去再复习数据结构的证明

反正他们就是同构的.

我们解决后者的问题, 即n个节点的二叉树有多少个型态?

首先这道题是可以使用括号问题来求解的: 问题同构映射:

将二叉树n节点假象为n对括号, 对第k个而言, 下一个左子即插入一对括号在括号内, 右子则括号外. 这样能够建立一个一一映射关系. 如 T(L, R) == (())() 而且是不重复的

由于二叉树的问题是去掉重复的, 而左边走步问题是针对限制条件的, 很难找一个映射过去.

再构建具有二叉树特色的计算方案把. 对于抽象数学差的我, 最后证明二叉树和走步问题同构只能通过证明等式了

考虑二叉树n个节点, 我们先fix头节点(root), 之后再考虑往左边和右边放的情况. 类似到二项式定理那种组合方法,很容易得到: 左边的子树的节点数目设为k从0到n-1, 右边则是n-k节点的子树.

不会重复, 考虑fp递归思想, 返回的是不会重复的 f(x) 那么就有, 左边的子树和右边的子树毫无关系, 更加不会重复了.

他们的聚合(aggregation)计算是积, 这一点根据组合的乘法就能推理出来了.

所以出现了第二个定义式子, 并且是以递归定义的:

式子中的 n-1 和 0 需要进行特色化…他可能是n和0, n和1, n-1和0, n-1和1…. 所以要处理好边界问题。

def num_trees(n):

    """How many full binary trees have exactly n leaves? E.g.,

    if n == 1: 

        return 1

    return sum([num_trees(k)*num_trees(n-k) for k in range(1, n)])

 96. 不同的二叉搜索树

那么这道题又怎么和 catalan 数扯上关系呢?(当然从0到3分析的确是 1 1 2 5)其实题目里的信息还是有额外的信息量的,并不是说给一系列数字然后求他们的 BST 总数,而是从 1 到 n 这么些数字来组成二叉搜索树。

如果从上面讲的01序列的要求来讲的话,递归分析无非就是如果选一个数字 n 做 root,那么其左边的总数是前n-1个数的总数,右边子树是后面的 n-k(这里是因为 k+1,...,n 的种类等价于 1,...,n-k 的种类,因为这两个问题是双射) 。所以能得到这个式子:也就是卡特兰数的的递归求和定义式。

G(n) = G(0)*G(n-1)+G(1)*(n-2)+...+G(n-1)*G(0)

然而有一个点可以想到的是,对于 1到n 的 n 个数,每一种二叉树都能和这些数字建立一个映射。

读者或者可以从二叉树来思考,对于n个节点的二叉树种类,每一种都的确只有 n 个节点,而如果想要他成为二叉搜索树,就把数字填进去就行了,而任何二叉树的都可以通过中序遍历得到一个序列,这个序列只需要填上 n 个数,就成为 BST 了。

所以这个 BST 的限制和 1-n 根本就没有意义,问题还是等同于上面说的n个节点二叉树的种类,然后又等价于 n 个叶子的完全二叉树的种类,又等价于 n 对括号的合法匹配,又等价于特定零一序列的生成问题,又等价于对角边界的寻路问题。

其实这种思路是转化与化归的思想,如果一个问题是递归定义容易理解的话,然后可以通过数学变换得到一个其他形式的定义,但是直接从那个形式来理解可能难些(因为他背后的东西可能会很多)。


刷题指南

知道上述应用场景,然后记忆卡特兰数 Catalan Number 的前几项: 1,1,2,5,14,42,132

另外注意上述 4 个推理定义的问题, 他们可以作为同构模型, 只要能找到一个双射把问题和他们联系起来

常见的问题模型

  • n层的阶梯切割为n个矩形的切法数
  • 对凸n+2边形进行不同的三角形分割的方案数(分割线断点仅为顶点,且分割线仅在顶点上相交)
  • n对括号的合法配对方案书
  • n个节点的二叉树的形态数
  • n+1个叶子(n个非叶节点)的满二叉树的形态数, 走到左儿子+1,走到 右儿子-1,类似于括号匹配(大致同2)
  • n个数入栈后出栈的排列总数

功利性总结

  • 二叉树种类问题
  • () -> 1
  • ()(), (()) -> 2
  • n = 3 -> 5
  • 括号匹配问题
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值