Given n, how many structurally unique BST's (binary search trees) that store values 1 ... n?
Example:
Input: 3 Output: 5 Explanation: 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个node。问这N个节点能组成多少个独一无二的二叉搜索树。这里我参考了喜刷刷的思路。注意既然是组成二叉搜索树,那么也就意味着左子树的节点需要小于根节点,右子树的节点需要大于根节点,而且这里面任何一个节点都可以当做根节点来用。注意到比如题目给的这个例子,N = 3,
- 当根节点为1的时候,左子树有0个元素(唯一一种情况),右子树有2个元素,而且右子树可以有两种情况(比如第一个树和最后一个树),所以当根节点为1的时候,组成的BST有可能有1 * 2 = 2种情况
- 当根节点为2的时候,左子树有1个元素(一种情况),右子树有1个元素(一种情况),所以组成的BST有1 * 1 = 1种情况
- 当根节点为3的时候,左子树有2个元素(两种情况),右子树有0个元素(一种情况),所以组成的BST有2 * 1 = 2种情况
总计2 + 1 + 2 = 5种情况
所以才会有这个公式,可以把他记成左边的情况 * 右边的情况
f(n) = f(0) * f(n-1) + f(1) * f(n-2) + ... + f(n-2) * f(1) + f(n-1) * f(0)
设dp[n]是最后能用n个node组成的BST的数量/情况。其中base case是dp[1] = 1,i代表可用的节点个数,j代表左子树上可用的节点个数,所以j的范围才是[0, i),因为需要留一个节点当做根节点。当有n个node的时候,需要先选定一个node作为根节点,然后需要算出以这个node为根节点的情况下,左子树可以有几种情况和右子树可以有几种情况。几个base case的结果如下,
dp[1] = 1, dp[2] = 2, dp[3] = 5, dp[4] = 14
时间O(n)
空间O(n)
Java实现
1 class Solution { 2 public int numTrees(int n) { 3 int[] res = new int[n + 1]; 4 res[0] = 1; 5 for (int i = 1; i <= n; i++) { 6 for (int j = 0; j < i; j++) { 7 res[i] += res[j] * res[i - 1 - j]; 8 } 9 } 10 return res[n]; 11 } 12 }
JavaScript实现
1 /** 2 * @param {number} n 3 * @return {number} 4 */ 5 var numTrees = function (n) { 6 var res = new Array(n + 1).fill(0); 7 res[0] = 1; 8 for (var i = 1; i <= n; i++) { 9 for (var j = 0; j < i; j++) { 10 // j代表左子树有几种情况,i - j - 1代表右子树有几种情况 11 res[i] += res[j] * res[i - j - 1]; 12 } 13 } 14 return res[n]; 15 };
还有一个非常好的discussion。