力扣-96-不同的二叉搜索树
小米2020的秋招笔试卷遇到了
n个节点可以构成多少不同的二叉搜索树?
- f(1) = 1
- f(2) = f(1) + f(1)
- f(3) = f(2) + f(1)*f(1) + f(2)
- … …
由此,我们可以得到递推式:
f(n) = f(n-1) + f(n-2)\*f(1) + … + f(1)\*f(n-2) + f(n-1)
打表是这样的:case 1: return 1;
case 2: return 2;
case 3: return 5;
case 4: return 14;
case 5: return 42;
case 6: return 132;
case 7: return 429;
case 8: return 1430;
case 9: return 4862;
case 10: return 16796;
case 11: return 58786;
它的推导过程是怎么推导的呢?
两个函数:
- G(n):表示n个不同节点组成的不同的二叉搜索树数量
- F(i,n):表示以i为根节点,n个节点组成的二叉搜索树的数量
对于序列{1~n},从中依次选择i作为根节点构造不同的二叉搜索树,因为根节点不同,所以一定是不同的二叉搜索树
而对于其左右子树,递归上述过程
那么G(n)=F(1,n)+…+F(n,n)
又对于F(i,n)而言,左子树不同的二叉搜索树数量为:G(i-1)=F(1,i-1)+…+F(i-1,i-1),右子树G(n-i)
则G(n)=G(0)*G(n)+……+G(n)*G(0)=G(i-1)*G(n-i)
一个看起来那么复杂的题做出来却是这么简单的代码
class Solution { public: int numTrees(int n) { vector<int> dp(n+1); dp[0] = 1; for (int i = 1; i <= n; i++) for (int j = 1; j <= i; j++) dp[i] += dp[j - 1] * dp[i - j]; return dp[n]; } };
它恰好就是力扣-96题
直达链接
二叉搜索树
复习一下二叉搜索树
- 左子树节点小于根节点
- 右子树节点大于根节点
我记起来的就是二叉搜索树的中序遍历结果是一个升序数组,那么对二叉搜索树进行中序遍历,在这个过程中判断新加入的值是否比上一个值大
非常要注意的是节点值相同不满足二叉搜索树定义
class Solution { public: bool res = true;// 因为递归方法不能有返回值,所以定义全局的变量记录结果 long preNum = (long)INT_MIN-1; void inorderTraversal(TreeNode* root) { if (!root) return; inorderTraversal(root->left); if (root->val <= preNum) { res = false; return; } else preNum = root->val; inorderTraversal(root->right); } bool isValidBST(TreeNode* root) { inorderTraversal(root); return res; } };
这里if判断中的return能够结束整个递归过程吗?其实是不行的,他只能结束自己向下的分支,就像第一句return也不会结束掉整个递归过程一样,所以说是有效率损失的,多余的遍历检查
本文作者:YaosGHC
本文链接:https://www.cnblogs.com/yaocy/p/16720002.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步