题意:
解题思路:
思路1:动态规划假设n个节点存在令G(n)的从1到n可以形成二叉排序树个数令f(i)为以i为根的二叉搜索树的个数即有:G(n) = f(1) + f(2) + f(3) + f(4) + ... + f(n)1. n为根节点,当i为根节点时,2. 其左子树节点个数为[1,2,3,...,i-1],3. 右子树节点个数为[i+1,i+2,...n],所以当i为根节点时,其左子树节点个数为i-1个,右子树节点为n-i,即f(i) = G(i-1)*G(n-i),上面两式可得:G(n) = G(0)*G(n-1)+G(1)*(n-2)+...+G(n-1)*G(0)N cnt 组合1 1 [1] => 1种2 2 [12] [21] => 2种3 5 1 2 3 => 5种针对i = 3,当选择1为根节点时:dp[1-1] * dp[3-1] => dp[0] * dp[2] :左边没有节点,右边有2个节点,可以组成:[123],[132]当选择2为根节点时:dp[2-1] * dp[3-2] => dp[1] * dp[1] :左边一个节点,右边一个节点,可以组成:[中左右]:[213]当选择3为根节点时:dp[3-1] * dp[3-3] => dp[2] * dp[0] :左边2个节点,右边没有节点,可以组成:[3,2,1][3,1,2]所以当选择3时:dp[0] * dp[2] + dp[1] * dp[1] + dp[2] * dp[0] = 5得出递推公式:d[i] = d[j-1] * d[$i-j];j = 1~i;=>j从1遍历到i,最后返回dp[n]思路2:对于每一个根i他都是由左边子树(1, 2, ..., i - 1)和右边子树(i + 1, i + 2, ..., n)组成的。因此他的个数肯定是两个子树情况的积。而且,这种根一共有n个,再将这些加起来就可以了。
PHP代码实现:
class Solution { /** * @param Integer $n * @return Integer */ function numTrees($n) { //return $this->numTrees1($n); if ($n <= 1) return 1; $dp[0] = 1; $dp[1] = 1; for ($i = 2; $i <= $n; $i++) { for ($j = 1; $j <= $i; $j++) { //左子树:$dp[$j - 1] //右子树:$dp[$i - $j] $dp[$i] += $dp[$j - 1] * $dp[$i - $j]; } } return $dp[$n]; } function numTrees1($n) { if ($n <= 1) return 1; $res = 0; for ($i = 0; $i < $n; $i++) { $res += $this->numTrees1($i) * $this->numTrees1($n - $i - 1); } return $res; }}
GO代码实现:
func numTrees(n int) int { G := make([]int, n + 1) G[0], G[1] = 1, 1 for i := 2; i <= n; i++ { for j := 1; j <= i; j++ { G[i] += G[j-1] * G[i-j] } } return G[n]}