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
法I:后序遍历。同Unique Binary Search Trees II,只是现在要返回的是数量,而无需将子树的所有情况放在数组中返回。
class Solution { public: int numTrees(int n) { if(n==0) return 0; else return postOrderTraverse(1,n); } int postOrderTraverse(int start, int end) { if(start == end){ //递归结束条件:碰到叶子节点(没有子节点) return 1; } int leftNum, rightNum, num=0; for(int i = start; i<=end; i++){ //iterate all roots leftNum = 0; rightNum = 0; if(i > start){ //count left tree leftNum = postOrderTraverse(start, i-1); } if(i < end){ //count right tree rightNum = postOrderTraverse(i+1, end); } //visit root: count number for each (leftTree, rightTree) pair if(leftNum==0) num+=rightNum; else if(rightNum==0) num+=leftNum; else num+=leftNum*rightNum; } return num; } };
Result: Time Limit Exceeded
法II:法I超时的原因是进行了很多重复计算。比如,在1-3的子树数量和4-6子树数量是相通的,因为它们的数字跨度相同。
解决方法是用动态规划存储每种数字跨度下的子数数量
class Solution { public: int numTrees(int n) { if(n==0) return 0; int dp[n+1]; dp[0] = 0; dp[1] = 1; for(int i = 2; i <= n; i++){ dp[i] = 0; //initialize for(int j = 1; j <= i; j++){ //traverse root if(i-j>0 && j>1) //左、右子树都存在 dp[i] += dp[j-1]*dp[i-j]; else if(j>1) //only left tree dp[i] += dp[j-1]; else //only right tree dp[i] += dp[i-j]; } } return dp[n]; } };