博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
LeetCode 96——不同的二叉搜索树
阅读量:6625 次
发布时间:2019-06-25

本文共 2565 字,大约阅读时间需要 8 分钟。

1. 题目

2. 解答

1, 2, \cdots, n 构建二叉搜索树,其中,任意数字都可以作为根节点来构建二叉搜索树。当我们将某一个数字作为根节点后,其左边数据将构建为左子树,右边数据将构建为右子树。因此,这是一个递归问题。

若以第 i 个数据为根节点,其左边数据有 i-1 个,左子树可能情况为 left_num,右边数据有 n-i 个,右子树可能情况为 right_num,因此以当前数据为根节点可以构建出 left_num * right_num 个二叉搜索树。

所以,我们要做的就是遍历 i = 1\cdots n,统计出每个数据作为根节点可以构建出的二叉搜索树总个数即可。

  • 递归法
class Solution {
public: int numTrees(int n) { int sum = 0; if (n <= 1) return 1; // 以当前的数为根节点,左右两边的数分别构建子树 for (int i = 1; i <= n; i++) { int left_num = numTrees(i - 1); // 左边的数可以构建多少个二叉搜索树 int right_num = numTrees(n - i); // 右边的数可以构建多少个二叉搜索树 sum += left_num * right_num; } return sum; }};复制代码

但是上面的程序运行时超时了,其实我们只需要统计一半数据就可以了,因为两边是对称的。

比如我们有 1,2,3,4,5 五个数,以 2 作为根节点,左边有 1 个数,右边有 3 个数。以 4 作为根节点,左边有 3 个数,右边有 1 个数。这两种情况是一样的,因此如果数据个数为偶数,我们只需要统计一半数据即可,而为奇数的话我们就要再多统计一个中间数据。

class Solution {
public: int numTrees(int n) { int sum = 0; if (n <= 1) return 1; int is_odd = n % 2; int mid = n / 2; // 以当前的数为根节点,左右两边的数分别构建子树 for (int i = 1; i <= mid; i++) { int left_num = numTrees(i - 1); // 左边的数可以构建多少个二叉搜索树 int right_num = numTrees(n - i); // 右边的数可以构建多少个二叉搜索树 sum += left_num * right_num; } sum = sum * 2; if (is_odd) sum = sum + numTrees(mid) * numTrees(n - mid - 1); return sum; }};复制代码

此外,我们还可以定义一个全局变量,来存放已经计算过的数值,避免在递归过程中大量地重复计算。

class Solution {
public: #define MAX 1000 int nums[MAX]; // 存放已经计算过的数值 int numTrees(int n) { int sum = 0; //if (n <= 0) return 1; if (n <= 1) return 1; // 以当前的数为根节点,左右两边的数分别构建子树 for (int i = 1; i <= n; i++) { if (nums[i-1] == 0) nums[i-1] = numTrees(i - 1); // 左边的数可以构建多少个二叉搜索树 int left_num = nums[i-1]; if (nums[n-i] == 0) nums[n-i] = numTrees(n - i); // 右边的数可以构建多少个二叉搜索树 int right_num = nums[n-i]; sum += left_num * right_num; } return sum; }};复制代码
  • 迭代法 还可以将递归改写为循环,避免函数多次调用执行效率较低。
class Solution {
public: int numTrees(int n) { int nums[n+1] = {
0}; nums[0] = 1; nums[1] = 1; if (n <= 1) return 1; for (int i = 2; i <= n; i++) { // 从 n=2 开始统计可以构建多少个不同的二叉搜索树 for (int j = 1; j <= i; j++) { nums[i] += nums[j-1] * nums[i-j]; } } return nums[n]; }}; 复制代码

获取更多精彩,请关注「seniusen」!

转载地址:http://jvxpo.baihongyu.com/

你可能感兴趣的文章
《黑客免杀攻防》读书笔记-软件逆向工程(6) switch-case分支
查看>>
day6作业--游戏人生完善
查看>>
金字塔思维
查看>>
strak组件(10):批量操作
查看>>
thinkphp空控制器的处理
查看>>
Mahout分步式程序开发 聚类Kmeans(转)
查看>>
修改linux最大文件句柄数
查看>>
接口幂等
查看>>
LibreOffice 打开中文乱码
查看>>
FromBottomToTop第十三周项目博客
查看>>
Activity的四种启动模式
查看>>
Centos vsftpd服务器搭建
查看>>
【常用工具】常用工具收集
查看>>
Tax
查看>>
网站页面多出&65279出现空白行的原因及解决方法
查看>>
第二阶段团队冲刺站立会议06
查看>>
html
查看>>
本地wampserver如何配置伪静态
查看>>
【转载】支持向量机SVM(一)
查看>>
C#串口通信实例
查看>>