题目描述链接:https://leetcode-cn.com/problems/unique-binary-search-trees/
解题思路:参考LeetCode题解,总结解题思路如下。分析:设F[i,n]表示长度为n的序列,用i为根的二叉搜索树总类。G[n]表示长度为n的序列的二叉搜索树的总类。
首先对于G[n]可以得到G[n]=F[1,n]+F[2,n]+...+F[n,n]。
而F[i,n]=G[i-1]*G[n-i] 这里是由于当我们选取i为根时,比i小的数有i-1个,而比i大的数有n-i,对于i-1个比i小的数的二叉搜索树的种类为G[i-1],而每个i为根的左子树
都对应与G[n-i]个右子树,故为F[i,n]=G[i-1]*G[n-i]。
所以得到G[n]=F[1,n]+F[2,n]+...+F[n,n]=G[1-1]*G[n-i]+G[2-1]*G[n-2]+...+G[i-1]*G[n-i]+...+G[n-1]*G[n-n]
从这样的一个递推函数当中容易想出可以采用递归或者动态规划的方法进行求解。而观察上式发现重在大量的重复计算,所以选用动态规划将中间结果保存的方式,进
行求解的效率较高。所以采用动态规划方法(另外观察公式也可以看出其满足卡特兰数,也可以采用卡特兰数进行求解),按照动态规划三部曲,进行编程思路分析。
(1)状态确定:G[i]表示n=i是的二叉搜索树方案数
(2)边界确定:G[0]=G[1]=1;
(3)状态转移方程:G[n]=G[1-1]*G[n-i]+G[2-1]*G[n-2]+...+G[i-1]*G[n-i]+...+G[n-1]*G[n-n]
根据以上得到LeetCode C++参考代码如下:
class Solution { public: int numTrees(int n) { vector<int>G(n+1); G[0]=1; G[1]=1; for(int i=2;i<=n;i++){ for(int j=1;j<=i;j++){ G[i]+=G[j-1]*G[i-j]; } } return G[n]; } };