热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

java编程求卡特兰数_从一道动态规划题带你领略『卡特兰数』是如何秒杀算法题的...

一、leetcode96号题题意:给定一个整数n,求以1…n为节点组成的二叉搜索树有多少种?n3时:二、动态规划思路

一、 leetcode 96 号题

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

n = 3 时:

37bda150e1bd188134706328cc74f92c.png

二、动态规划

思路:从 1 开始到 n ,每次以这个数为根,左子树存放比它小的数,右子树存放比它大的数。每个根不重复,因此每个树也必定不重复。

左子树和右子树,又可以按照这个规则去生成新的树。

1c04a6c46ed1f1ab5c1bcaa1cdc8f603.png

例如:n = 3的时候

1为根:比 1 小的数只有 0,不用管。比 1 大的数有 2 和 3。

拿 2 和 3 来生成一棵树和拿 1 和 2 来生成一棵树的种数是不是相同的?那么 1 和 2 能生成多少种树呢?

2为根:比 2 小的是 1,比 2 大的是 3。这里只有 1 种。

3为根:比 3 小的是 1 和 2,1 和 2 能生成多少种树呢?

我们先暂停思维,来到一个新的问题。n = 2 的时候,结果应该是多少?

3929d8360ba5861ba919d7a8623888c7.png

n = 2 的时候,按照我们之前的方法。

1 为根:比 1 大的数只有 2, 这里有 1 种。

2 为根:比 2 小的数只有 1, 这里有 1 种。

那答案就应该是 2 种。

解决了 n = 2 的问题,那 n = 3 的问题就也解决了。ans = 2 + 1 + 2 = 5。

我们来看一般情况。输入一个 n 。

定义一个 F(i) 表示以 i 为根,生成的树的种数。

定义一个 G(n) 表示输入 n 的时候,输出的结果。此处一定要注意 F 与 G 的区别。

以 i 为根的时候,能生成多少种树?

比 i 小的有 i - 1 个,比 i 大的有 n - i 个。因此左子树有 i - 1 个, 右子树有 n - i 个数。那么,F(i) = G(i - 1) * G(n - i)。

而我们求的 G(n) = F(1) + F(2) + …… + F(n)。

把两个公式综合 :

747bbe756541d342c2e8ed64958b6ac6.png

d[0] = 1; // 0 的时候特殊处理

for (int i &#61; 1; i <&#61; n; i&#43;&#43;)

for (int j &#61; 1; j <&#61; i; j&#43;&#43;)

d[i] &#43;&#61; d[j-1] * d[i-j];

以上是利用动态规划求解的思路。

时间复杂度&#xff1a;O(n^2)

空间复杂度&#xff1a;O(n)

三、 Catalan公式

这个题目还有一种很强的解法&#xff0c;卡特兰公式。卡特兰公式和排列组合有很大关系&#xff0c;不属于偏难怪解法&#xff0c;有很多算法和数据结构的问题本质上就是卡特兰公式的应用。比如二叉树的形态数&#xff0c;出栈序列数&#xff0c;括号匹配问题等。公式不要紧&#xff0c;没必要去硬背。主要是理解卡特兰问题应用的特征&#xff0c;把问题抽象到已有模型中来。

Catalan 递推项满足&#xff1a;

C(n) &#61; C(0) C(n-1) &#43; C(1) C(n-2) &#43; … &#43; C(n-2) C(1) &#43; C(n-1) C(0)

Catalan 通项公式&#xff1a;

45a1322fb272af60342709dd438887aa.png &#61;

ee8a187a64b937d8716c5cea59453156.png

1b70dc9a94252ab6cd51339faeaff168.png

Catalan 递推公式1&#xff1a;

61786394b2620a4551c67b378060bc71.png &#61;

bb81d40264d4bc95ee5f0cd501dcfbcc.png

fdc627e03d472ce77846774045f9c213.png

Catalan 性质&#xff1a;

c5d71aecf4ba914a66b3d6b89976b336.png &#61;

73c34db04c31b495d948c9a914c762c3.png -

6ea3062948eaf94747609d9aa47202c5.png

这个题目里面&#xff0c;由我们上面的 G(n) 很容易可以看出是一个卡特兰的应用。

我们用它的递推公式来求解。

de83d840247e4504311a2bdcded597fc.png 的值&#xff0c;

8efa373ff5db6179befaf6e442e757c2.png &#61;

1c8f43d57c1fb8f21fe092db871b3ac9.png

bb07243b2774ccf39752d0c5a584b410.png。公式顺推&#xff0c;代码中 n 次循环结束后的 ans 值就是

81e8a7e678c6dcb5c513ed0d9632c57a.png 对应的值。类比斐波那契最简解法。

long ans &#61; 1;

for(int i &#61; 1; i <&#61; n; i&#43;&#43;)

ans &#61; ans * 2 * (2 * i &#43; 1) / (i &#43; 2);

return (int) ans;

时间复杂度&#xff1a;O(n)

空间复杂度&#xff1a;O(1)

四、Catalan应用

例题1&#xff1a;括号序列

给 n 对括号&#xff0c;可以合成的合法序列有多少种&#xff1f;

082c6570b230bd4e99fe777547c6f457.png

首先计算一共的序列种数。n 对括号&#xff0c; 一共有 2n 个位置。我们选出其中 n 个位置放放置左括号&#xff0c;剩下的位置肯定就是右括号了。因此一共的种数为&#xff1a;

a72cc898a7d542afd3d388ded636736d.png

接下来找出非法的括号序列数。每个非法的序列&#xff0c;在它的奇数位置&#xff0c;一定存在右括号数量大于左括号的数量。

fd7d6e03f1fd884487ff3d5dc661ad16.png

在上图中&#xff1a;第 2m &#43; 1 的时候&#xff0c;右括号大于左括号&#xff0c;因此该序列非法。

在 2m &#43; 1 前&#xff1a;

右括号数量为&#xff1a;m &#43; 1

左括号数量为&#xff1a;m

在 2m &#43; 1后&#xff1a;

总的数量&#xff1a;n - 2m - 1

左括号有&#xff1a;n - 2m - 1 - (m &#43; 1) &#61; n - m

右括号有&#xff1a;n - 2m - 1 - m &#61; n - m - 1

这个时候我们将右边的左括号和右括号位置置换(总的组合数量不会受到影响)。那么在整个序列 2n 个位置中&#xff1a;

右括号的数量为&#xff1a;m &#43; 1 &#43; n - m &#61; n &#43; 1

左括号的数量为&#xff1a;m &#43; n - m - 1 &#61; n - 1

在长度为 2n 里面有 n &#43; 1 个右括号&#xff0c;数量为&#xff1a;

7f97a2e469ab3a1d64017a84e45c4ed0.png 。你也可以理解从左括号的角度去看&#xff1a;

d300a38fb856d7a0803d3565d6ad3430.png

在上面两个步骤以后&#xff0c;我们得到的合法序列数&#xff1a;

866b40e76b3c18843bba8ff5a25e1615.png -

d3b281a1529c62265d332dd32d4c272b.png 。这就是 Catalan 公式的性质公式。知道是 Catalan&#xff0c;我们就可以用刚刚的方法求解问题的答案。

例题2 &#xff1a;一个栈(无穷大)的进栈序列为1&#xff0c;2&#xff0c;3&#xff0c;…&#xff0c;n&#xff0c;有多少个不同的出栈序列?

例题3 &#xff1a;给出一个n&#xff0c;要求一个长度为2n的01序列&#xff0c;使得序列的任意前缀中1的个数不少于0的个数&#xff0c; 有多少个不同的01序列?

例题4 &#xff1a;2n个人要买票价为五元的电影票&#xff0c;每人只买一张&#xff0c;但是售票员没有钱找零。其中&#xff0c;n个人持有五元&#xff0c;另外n个人持有十元&#xff0c;问在不发生找零困难的情况下&#xff0c;有多少种排队方法&#xff1f;(阿里有个笔试题根据这个变化的)

其他动态规划算法题推荐&#xff1a;

1、告别动态规划&#xff0c;连刷40道动规算法题&#xff0c;我总结了动规的套路

2、动态规划该如何优化&#xff1f;我总结了这些套路&#xff0c;以后优化就是分分钟

3、算法专题(动规)&#xff1a;不同的定义产生不同的解法

4、详解三道一维的动态规划算法题

5、经典动态规划&#xff1a;高楼扔鸡蛋

6、详解 leetcode 221 题&#xff1a;最大正方形

7、动态规划之正则表达式

推荐阅读

写了很久&#xff0c;这是一份适合普通大众/科班/非科班的『学习路线』

有必要说一说即将到来的春招(经历&#43;重要性&#43;如何准备)

普普通通&#xff0c;我的三年大学

历经两个月&#xff0c;我的秋招之路结束了&#xff01;



推荐阅读
  • JVM 学习总结(三)——对象存活判定算法的两种实现
    本文介绍了垃圾收集器在回收堆内存前确定对象存活的两种算法:引用计数算法和可达性分析算法。引用计数算法通过计数器判定对象是否存活,虽然简单高效,但无法解决循环引用的问题;可达性分析算法通过判断对象是否可达来确定存活对象,是主流的Java虚拟机内存管理算法。 ... [详细]
  • 提升Python编程效率的十点建议
    本文介绍了提升Python编程效率的十点建议,包括不使用分号、选择合适的代码编辑器、遵循Python代码规范等。这些建议可以帮助开发者节省时间,提高编程效率。同时,还提供了相关参考链接供读者深入学习。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 解决Cydia数据库错误:could not open file /var/lib/dpkg/status 的方法
    本文介绍了解决iOS系统中Cydia数据库错误的方法。通过使用苹果电脑上的Impactor工具和NewTerm软件,以及ifunbox工具和终端命令,可以解决该问题。具体步骤包括下载所需工具、连接手机到电脑、安装NewTerm、下载ifunbox并注册Dropbox账号、下载并解压lib.zip文件、将lib文件夹拖入Books文件夹中,并将lib文件夹拷贝到/var/目录下。以上方法适用于已经越狱且出现Cydia数据库错误的iPhone手机。 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
author-avatar
书友8649571
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有