作者: 负雪明烛
id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/


题目地址:https://leetcode.com/problems/unique-binary-search-trees/description/

题目描述

Given n, how many structurally unique BST’s (binary search trees) that store values 1...n?

For example,

Given n = 3, there are a total of 5 unique BST's.

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

题目大意

给了一个数字n,问n个节点的二叉树有多少种?

解题方法

记忆化递归

思路:从1...n中找出一个i作为根节点,比i小的数1...i-1作为左子树,比i大的数i+1...n作为右子树,左子树的排列和右子树的排列的乘积是此时的数目。

因为直接递归会超时,所以加上了记忆化搜索的方法,这样就快的多了。

class Solution(object):
def __init__(self):
self.dp = dict() def numTrees(self, n):
"""
:type n: int
:rtype: int
"""
if n in self.dp:
return self.dp[n]
if n == 0 or n == 1:
return 1
ans = 0
for i in range(1, n + 1):
ans += self.numTrees(i - 1) * self.numTrees(n - i)
self.dp[n] = ans
return ans

使用C++代码和上面类似,同样使用记忆化搜索能够完成。只不过,这里需要注意的一点是,左边的孩子数目是i的时候,右边的孩子数目因该是n - 1 - i,因为要去掉根节点。

代码如下:

class Solution {
public:
int numTrees(int n) {
if (n == 0) return 1;
if (m_.count(n)) return m_[n];
int res = 0;
for (int i = 0; i < n; i++) {
int left = numTrees(i);
int right = numTrees(n - 1 - i);
res += left * right;
}
return m_[n] = res;
}
private:
unordered_map<int, int> m_;
};

动态规划

同样是上面的思路,如果使用动态规划去做,可以设dp[i]是i个节点的二叉树有多少种组合。那么,很明显和上面解法一样的,dp[i]等于左子树有0个节点,左子树有1个节点,左子树有2个节点……等等情况下的和。对于左右子树的组合方式是独立事件,所以总的组合数是左右子树相乘的关系。

完整的推导在下面,参照了:http://blog.csdn.net/u012501459/article/details/46622501

给定一个数n,求1到n这些数可以构成多少棵二叉树。
给定一个序列1.....n,为了构造所有二叉树,我们可以使用1......n中的每一个数i作为根节点,自然1......(i-1)必然位于树的左子树中,(i+1).....n位于树的右子树中。然后可以递归来构建左右子树,由于根节点是唯一的,所以可以保证构建的二叉树都是唯一的。 使用两个状态来记录: G(n):长度为n的序列的所有唯一的二叉树。 F(i,n),1<=i<=n:以i作为根节点的二叉树的数量。 G(n)就是我们要求解的答案,G(n)可以由F(i,n)计算而来。 G(n)=F(1,n)+F(2,n)+...+F(n,n) (1) G(0)=1,G(1)=1 对于给定的一个序列1.....n,我们取i作为它的根节点,那么以i作为根节点的二叉树的数量F(i)可以由下面的公式计算而来: F(i,n)=G(i-1)*G(n-i) 1<=i<=n (2) 综合公式(1)和公式(2),可以看出: G(n) = G(0) * G(n-1) + G(1) * G(n-2) + … + G(n-1) * G(0) 这就是上面这个问题的答案。

答案:

class Solution(object):
def numTrees(self, n):
"""
:type n: int
:rtype: int
"""
dp = [1, 1]
for i in xrange(2, n + 1):
count = 0
for j in xrange(i):
count += dp[j] * dp[i - j - 1]
dp.append(count)
return dp.pop()

上面的做法的C++代码如下:

class Solution {
public:
int numTrees(int n) {
// how many trees if the total tree has dp[i] nodes.
vector<int> dp(n + 1);
dp[0] = dp[1] = 1;
for (int i = 2; i < n + 1; i ++) {
for (int j = 0; j < i; j++) {
dp[i] += dp[j] * dp[i - 1 - j];
}
}
return dp[n];
}
};

卡特兰数

卡塔兰数的一般项公式为

h(0)=1,h(1)=1,卡塔兰数数满足递归式:

h(n)= h(0)*h(n-1) + h(1)*h(n-2) + ... + h(n-1)h(0) (其中n>=2)这是n阶递归关系;

该递推关系的解为:

h(n)=C(2n,n)/(n+1)=P(2n,n)/(n+1)!=(2n)!/(n!*(n+1)!) (n=1,2,3,...)

代码如下:

class Solution {
public:
int numTrees(int n) {
// how many trees if the total tree has dp[i] nodes.
long long res = 1;
for (int i = n + 1; i <= 2 * n; i++) {
res = res * i / (i - n);
}
return res / (n + 1);
}
};

卡特兰数的前20项是固定的,也就可以直接返回对应的数字即可。

class Solution {
public:
int numTrees(int n) {
// how many trees if the total tree has dp[i] nodes.
vector<int> dp = {1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670, 129644790, 477638700, 1767263190};
return dp[n];
}
};

日期

2018 年 2 月 25 日
2018 年 12 月 31 日 —— 2018年最后一天!

【LeetCode】96. Unique Binary Search Trees 解题报告(Python & C++)的更多相关文章

  1. [LeetCode] 96. Unique Binary Search Trees 唯一二叉搜索树

    Given n, how many structurally unique BST's (binary search trees) that store values 1...n? For examp ...

  2. 52. leetcode 96. Unique Binary Search Trees

    96. Unique Binary Search Trees Given n, how many structurally unique BST's (binary search trees) tha ...

  3. leetcode 96. Unique Binary Search Trees 、95. Unique Binary Search Trees II 、241. Different Ways to Add Parentheses

    96. Unique Binary Search Trees https://www.cnblogs.com/grandyang/p/4299608.html 3由dp[1]*dp[1].dp[0]* ...

  4. [LeetCode] 96. Unique Binary Search Trees(给定一个数字n,有多少个唯一二叉搜索树) ☆☆☆

    [Leetcode] Unique binary search trees 唯一二叉搜索树 Unique Binary Search Trees leetcode java 描述 Given n, h ...

  5. [LeetCode] 96. Unique Binary Search Trees 独一无二的二叉搜索树

    Given n, how many structurally unique BST's (binary search trees) that store values 1 ... n? Example ...

  6. Java [Leetcode 96]Unique Binary Search Trees

    题目描述: Given n, how many structurally unique BST's (binary search trees) that store values 1...n? For ...

  7. leetcode 96 Unique Binary Search Trees ----- java

    Given n, how many structurally unique BST's (binary search trees) that store values 1...n? For examp ...

  8. [leetcode]96. Unique Binary Search Trees给定节点形成不同BST的个数

    Given n, how many structurally unique BST's (binary search trees) that store values 1 ... n? Input: ...

  9. [leetcode] 96 Unique Binary Search Trees (Medium)

    原题 字母题 思路: 一开始妹有一点思路,去查了二叉查找树,发现有个叫做卡特兰数的东西. 1.求可行的二叉查找树的数量,只要满足中序遍历有序. 2.以一个结点为根的可行二叉树数量就是左右子树可行二叉树 ...

随机推荐

  1. Redis源码解析(1)

    在文章的开头我们把所有服务端文件列出来,并且标示出其作用: adlist.c //双向链表 ae.c //事件驱动 ae_epoll.c //epoll接口, linux用 ae_kqueue.c / ...

  2. 突破冯·诺依曼架构瓶颈!全球首款存算一体AI芯片诞生

    过去70年,计算机一直遵循冯·诺依曼架构设计,运行时数据需要在处理器和内存之间来回传输. 随着时代发展,这一工作模式面临较大挑战:在人工智能等高并发计算场景中,数据来回传输会产生巨大的功耗:目前内存系 ...

  3. 学习Java的第十八天

    一.今日收获 1.java完全学习手册第三章算法的3.1比较值 2.看哔哩哔哩上的教学视频 二.今日问题 1.在第一个最大值程序运行时经常报错. 2.哔哩哔哩教学视频的一些术语不太理解,还需要了解 三 ...

  4. Applescript快速入门及OmniFocus每日md报告开发

    本篇主要记录 Applescript 基础语法,以及利用 applescript 生成 omnifocus 每日报告 从 windows 转换到 macos,最近一直在不断折腾,这两天浏览 githu ...

  5. 大数据学习day11------hbase_day01----1. zk的监控机制,2动态感知服务上下线案例 3.HDFS-HA的高可用基本的工作原理 4. HDFS-HA的配置详解 5. HBASE(简介,安装,shell客户端,java客户端)

    1. ZK的监控机制 1.1 监听数据的变化  (1)监听一次 public class ChangeDataWacher { public static void main(String[] arg ...

  6. Linux磁盘分区(四)之分区大小调整

    Linux磁盘分区(四)之分区大小调整在学习调整分区大小之前,先了解linx分区的概念.参考如下博客:[1]linux 分区 物理卷 逻辑卷 https://www.cnblogs.com/liuch ...

  7. ORACLE profile含义,修改,新增

    profiles文件是口令和资源限制的配置集合,包括CPU的时间.I/O的使用.空闲时间.连接时间.并发会话数量.密码策略等对于资源的使用profile可以做到控制会话级别或语句调用级别.oracle ...

  8. 【编程思想】【设计模式】【行为模式Behavioral】command

    Python版 https://github.com/faif/python-patterns/blob/master/behavioral/command.py #!/usr/bin/env pyt ...

  9. new Date()与setDate()参数

    New Date()与setDate()参数 相信网上已经有很多关于日期的文章了,这里只是我自己再工作中遇到的问题然后加以总结: new Date() new Date() 一共有六种形式,五种带参数 ...

  10. Flutter 中如何优雅的实现多渠道打包(埋点统计系列)

    我是 Zero,脑图先奉上 先赞后看,更新永不断 只要你关注 Flutter,这篇文章你绝对用得着,==> 强烈建议收藏 多渠道打包介绍 多渠道打包的主要作用是满足产品的运营需求,统计渠道和活动 ...