Leetcode 96 Unique Binary Search Trees
来源:互联网 发布:2016淘宝详情页尺寸 编辑:程序博客网 时间:2024/06/04 18:40
原题地址:https://leetcode.com/problems/unique-binary-search-trees/
题目描述
Given n, how many structurally unique BST’s (binary search trees) that store values 1…n?
给出n,返回结构上不重复的二叉查找树的个数(每个二叉树都存储1,2,3,…,n)。
For example,
举例,
Given n = 3, there are a total of 5 unique BST’s.
给出n=3,共有5种各异的二叉查找树:
1 3 3 2 1 \ / / / \ \ 3 2 1 1 3 2 / / \ \ 2 1 2 3
对于 n=3,返回 5 。
解题思路
这是一个动态规划问题。
由于我是先做的Leetcode 95(博客记录:Leetcode 95 Unique Binary Search Trees II),因此很自然得认为想到在Leetcode 95的基础上对程序进行修改即可轻松得到正确的代码。然而仅仅修改代码遇到了以下问题:
1. Memory Limit Exceeded 超过内存限制2. Time Limit Exceeded 超过时间限制
为了解决上述方法,我主要采取以下方法来优化代码:
1. 特别注意对于内存的管理,对于已经不再使用的内存及时进行释放。2. 有些情况下是无须重复计算的,如果重复计算的话就会有超时的可能。
对于第一点,这个没什么技巧, 对于无用的内存释放即可。
对于第二点,我们可以发现如下规律,对于两个不存在重复元素的数组arr1和arr2,当他们元素数量相同时,就算他们存储的元素不全都一样,他们可以构成的二叉查找树是一样多的。因此我们考虑使用一个数组numsTrees[n+1]来存储可以构成的异构二叉查找树的数目,这样只需要计算n+1次,其他情况下直接使用已经存储的结果即可。这是一种以空间换时间的方法。空间复杂度O(n),时间复杂度O(n)。
代码
/** * 返回由n个数字可以构成的异构二叉查找树的数目 * Input n : 最大值(即1-n共n个数) * Return : 异构的二叉查找树的数目 */int numTrees(int n) { int numTreesFromArray(int *, int *, int); // 如果n为0或1,直接返回1 if (n == 0 || n == 1) return 1; // 分配备选数组nums内存 int *nums = (int *)malloc(sizeof(int) * n); // 分配numsTrees内存,numsTrees[i]代表用i个数可以构成的异构二叉查找树的数目 int *numsTrees = (int *)malloc(sizeof(int) * (n + 1)); // 初始化 int i; for (i = 0; i < n; ++i) { *(nums + i) = i + 1; // 初始化备选数组nums,nums中存储着1-n(有序) *(numsTrees + i) = 0; // 初始化结果集numsTrees = {0} } *(numsTrees + n) = 0; // 初始化numsTrees[n] = 0 *numsTrees = 1; // 初始化numsTrees[0] = 1,空集只有一种构造方式 *(numsTrees + 1) = 1; // 初始化numsTrees[1] = 1,一个数字只有一种构造方式 // 获取使用nums可能异构的二叉查找树的数目 int count = numTreesFromArray(numsTrees, nums, n); // 释放内存 free(nums); free(numsTrees); return count;}/** * 返回由nums数组中的元素可以构造出的异构的二叉查找树的数目 * Input numsTrees : 存储由i个元素可以构成的异构二叉查找树的数目 * Input nums : 存储备选元素 * Input size : 备选元素个数 * Return : 异构的二叉查找树的数目 */int numTreesFromArray(int *numsTrees, int *nums, int size) { // 如果已经计算过,直接返回 if (*(numsTrees + size)) return *(numsTrees + size); int *littleNums = (int *)malloc(sizeof(int) * size); // 用于存储比根节点小的数 int *bigNums = (int *)malloc(sizeof(int) * size); // 用于存储比根节点大的数 int littleNumsCount, bigNumsCount, i, j, k, count = 0; for (i = 0; i < size; ++i) { // 遍历nums中的元素,将其作为根节点的值 littleNumsCount = 0; // 初始化littleNums的数量 bigNumsCount = 0; // 初始化bigNums的数量 // 将nums分成比根节点小的和比根节点大的两个数组 for (j = 0; j < size; ++j) { if (*(nums + j) >= *(nums + i)) break; *(littleNums + littleNumsCount++) = *(nums + j); } if (*(nums + j) == *(nums + i)) ++j; for (; j < size; ++j) *(bigNums + bigNumsCount++) = *(nums + j); // 返回由littleNums可以构造出的异构的二叉查找树的数目 j = numTreesFromArray(numsTrees, littleNums, littleNumsCount); // 返回由bigNums可以构造出的异构的二叉查找树的数目 k = numTreesFromArray(numsTrees, bigNums, bigNumsCount); count += j * k; // 增加异构的二叉查找树的数目 } // 释放内存 free(littleNums); free(bigNums); // 存储结果 *(numsTrees + size) = count; return count;}
运行情况
Status:Accept
Time:0ms
测试数据
0 : 11 : 12 : 23 : 54 : 145 : 426 : 1327 : 4298 : 14309 : 486210 : 1679611 : 5878612 : 20801213 : 74290014 : 267444015 : 969484516 : 3535767017 : 12964479018 : 47763870019 : 1767263190
总结
运行时间竟然是0ms,之前的时候可是超时的啊,可见有些时候用空间来换时间还是非常值得的。代码优化的重要性也不言而喻。
// 个人学习记录,若有错误请指正,大神勿喷
// sfg1991@163.com
// 2015-05-26
- LeetCode 96 Unique Binary Search Trees II
- [leetcode 96] Unique Binary Search Trees
- Leetcode NO.96 Unique Binary Search Trees
- leetcode || 96、Unique Binary Search Trees
- [Leetcode 96, Medium] Unique Binary Search Trees
- leetcode-96 Unique Binary Search Trees
- Unique Binary Search Trees - LeetCode 96
- Leetcode 96 Unique Binary Search Trees
- Leetcode[96]-Unique Binary Search Trees
- Leetcode 96 Unique Binary Search Trees
- leetcode[96]:Unique Binary Search Trees
- [leetcode 96]Unique Binary Search Trees
- Leetcode # 96 Unique Binary Search Trees
- LeetCode(96) Unique Binary Search Trees
- [leetcode-96]Unique Binary Search Trees(c++)
- leetcode 96: Unique Binary Search Trees
- leetCode #96 Unique Binary Search Trees
- leetcode 95-96:Unique Binary Search Trees
- Android情景分析之深入解析system_server
- 字典树的C++实现
- Java中finally关键字的使用
- 为什么说Tomcat是一个Web服务器而不是一个应用服务器
- Servlet 中文乱码问题及解决方案剖析
- Leetcode 96 Unique Binary Search Trees
- js给table赋值
- Map Vector Set (离散的使用)
- Android 设置竖屏
- finished with non-zero exit value 2问题的常用解决方案
- FFT的物理意义 配波形图
- SSH项目中的文件划分
- 线程与进程的区别
- 对自定义UITableViewCell的理解