C++实现LeetCode(95.独一无二的二叉搜索树之二)
C++实现LeetCode(95.独一无二的二叉搜索树之二),恰卡网带你了解更多相关信息。
[LeetCode] 95. Unique Binary Search Trees II 独一无二的二叉搜索树之二
Given an integer n, generate all structurally unique BST's (binary search trees) that store values 1 ... n.
Example:
Input: 3
Output:
[
[1,null,3,2],
[3,2,null,1],
[3,1,null,null,2],
[2,1,3],
[1,null,2,null,3]
]
Explanation:
The above output corresponds to the 5 unique BST's shown below:1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
这道题是之前的 Unique Binary Search Trees 的延伸,之前那个只要求算出所有不同的二叉搜索树的个数,这道题让把那些二叉树都建立出来。这种建树问题一般来说都是用递归来解,这道题也不例外,划分左右子树,递归构造。这个其实是用到了大名鼎鼎的分治法 Divide and Conquer,类似的题目还有之前的那道 Different Ways to Add Parentheses 用的方法一样,用递归来解,划分左右两个子数组,递归构造。刚开始时,将区间 [1, n] 当作一个整体,然后需要将其中的每个数字都当作根结点,其划分开了左右两个子区间,然后分别调用递归函数,会得到两个结点数组,接下来要做的就是从这两个数组中每次各取一个结点,当作当前根结点的左右子结点,然后将根结点加入结果 res 数组中即可,参见代码如下:
解法一:
class Solution { public: vector<TreeNode*> generateTrees(int n) { if (n == 0) return {}; return helper(1, n); } vector<TreeNode*> helper(int start, int end) { if (start > end) return {nullptr}; vector<TreeNode*> res; for (int i = start; i <= end; ++i) { auto left = helper(start, i - 1), right = helper(i + 1, end); for (auto a : left) { for (auto b : right) { TreeNode *node = new TreeNode(i); node->left = a; node->right = b; res.push_back(node); } } } return res; } };
我们可以使用记忆数组来优化,保存计算过的中间结果,从而避免重复计算。注意这道题的标签有一个是动态规划 Dynamic Programming,其实带记忆数组的递归形式就是 DP 的一种,memo[i][j] 表示在区间 [i, j] 范围内可以生成的所有 BST 的根结点,所以 memo 必须是一个三维数组,这样在递归函数中,就可以去 memo 中查找当前的区间是否已经计算过了,是的话,直接返回 memo 中的数组,否则就按之前的方法去计算,最后计算好了之后要更新 memo 数组,参见代码如下:
解法二:
class Solution { public: vector<TreeNode*> generateTrees(int n) { if (n == 0) return {}; vector<vector<vector<TreeNode*>>> memo(n, vector<vector<TreeNode*>>(n)); return helper(1, n, memo); } vector<TreeNode*> helper(int start, int end, vector<vector<vector<TreeNode*>>>& memo) { if (start > end) return {nullptr}; if (!memo[start - 1][end - 1].empty()) return memo[start - 1][end - 1]; vector<TreeNode*> res; for (int i = start; i <= end; ++i) { auto left = helper(start, i - 1, memo), right = helper(i + 1, end, memo); for (auto a : left) { for (auto b : right) { TreeNode *node = new TreeNode(i); node->left = a; node->right = b; res.push_back(node); } } } return memo[start - 1][end - 1] = res; } };
到此这篇关于C++实现LeetCode(95.独一无二的二叉搜索树之二)的文章就介绍到这了,更多相关C++实现独一无二的二叉搜索树之二内容请搜索趣讯吧以前的文章或继续浏览下面的相关文章希望大家以后多多支持趣讯吧!
推荐阅读
-
手动挡汽车换挡速度达到多少合适(手动挡汽车的换挡速度该如何掌握)
手动挡汽车换挡速度的合适性是很多新手司机关心的问题。一般来说,手动挡汽车的换挡速度应该尽可能平稳,避免过快或过慢。具体而言,手动挡...
-
怎么得到兄弟的女朋友 睡兄弟老婆的方法介绍
如果是真心喜欢,既然人家已经有老公了,不建议去破坏人家家庭,默默祝福就好了。运用特殊手段是违法犯罪行为,合理表达自己的爱慕之心,真...
-
查看路由器宽带密码(如何找回路由器管理员密码)
如何查看路由器宽带密码?路由器是现代家庭和企业网络中必不可少的设备。它可以连接多个设备并实现共享网络资源。但是,有时我们需要查看路...
-
失业大军涌入外卖(骑手收入腰斩 外卖骑手感到无力和绝望)
近年来,随着中国经济的不断发展和消费习惯的转变,外卖行业在中国蓬勃发展。越来越多的人加入到外卖行业中,骑手数量也大量涌入。但现在,...
-
真皮皮鞋怎么保养(正确保养真皮皮鞋的小贴士)
皮鞋在我们的日常生活中是常见的鞋履之一,不仅款式多样,而且舒适耐穿。其中,真皮皮鞋是许多人的选择,因为它们具有高品质和永久耐用的特...
-
车改装了找黄牛(汽车改装需谨慎避免找黄牛)
车改装了找黄牛汽车改装是车主展示个人品味和个性的一种方式。然而,如果改装不当,不仅会影响车辆性能和安全,而且还会面临违法处罚的风险...
-
网卡怎么用在路由器上(如何在路由器上使用网卡)
对于一些家庭用户,如果家里的网络需要多个设备同时连接上网,那么路由器无疑是一个必不可少的工具。而网卡则是路由器中非常关键的一部分。...
-
龙城陈宇呈东霓为什么离婚(龙城陈宇呈是个什么样的人)
龙城中陈宇呈是郑东霓第一任丈夫,她们是自由恋爱后面离婚了,陈宇呈35岁,龙城血液中心医生。冷静理智,作为一个优秀的医生,他所有的判...
-
卡其色卫衣配什么裤子(卡其色卫衣的多种搭配方式)
卡其色卫衣是现代休闲装中的一种经典款式,不仅舒适实用,还充满了时尚感。然而,很多人却不知道该如何搭配裤子,以突出卡其色卫衣的特色。...
-
windows系统用苹果鼠标(如何在Windows系统中使用苹果鼠标)
如何在Windows系统中使用苹果鼠标?在日常使用中,很多人可能会遇到这样的问题:手头只有一只苹果鼠标,但使用的电脑却是Windo...