[LeetCode] 96. Unique Binary Search Trees

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

LeetCode 题目总结

原文地址:https://www.cnblogs.com/cnoodle/p/12290655.html