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 == ) return {};
return helper(, 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 - ), right = helper(i + , 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 == ) return {};
vector<vector<vector<TreeNode*>>> memo(n, vector<vector<TreeNode*>>(n));
return helper(, n, memo);
}
vector<TreeNode*> helper(int start, int end, vector<vector<vector<TreeNode*>>>& memo) {
if (start > end) return {nullptr};
if (!memo[start - ][end - ].empty()) return memo[start - ][end - ];
vector<TreeNode*> res;
for (int i = start; i <= end; ++i) {
auto left = helper(start, i - , memo), right = helper(i + , 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 - ][end - ] = res;
}
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/95

类似题目:

Unique Binary Search Trees

Different Ways to Add Parentheses

参考资料:

https://leetcode.com/problems/unique-binary-search-trees-ii/

https://leetcode.com/problems/unique-binary-search-trees-ii/discuss/31494/A-simple-recursive-solution

https://leetcode.com/problems/unique-binary-search-trees-ii/discuss/31535/20ms-C%2B%2B-top-down-DP-solution

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Unique Binary Search Trees II 独一无二的二叉搜索树之二的更多相关文章

  1. LeetCode: Unique Binary Search Trees II 解题报告

    Unique Binary Search Trees II Given n, generate all structurally unique BST's (binary search trees) ...

  2. [LeetCode] 95. Unique Binary Search Trees II 独一无二的二叉搜索树之二

    Given an integer n, generate all structurally unique BST's (binary search trees) that store values 1 ...

  3. LeetCode - Unique Binary Search Trees II

    题目: Given n, generate all structurally unique BST's (binary search trees) that store values 1...n. F ...

  4. [Leetcode] Unique binary search trees ii 唯一二叉搜索树

    Given n, generate all structurally unique BST's (binary search trees) that store values 1...n. For e ...

  5. LeetCode——Unique Binary Search Trees II

    Question Given an integer n, generate all structurally unique BST's (binary search trees) that store ...

  6. [LeetCode] Unique Binary Search Trees II dfs 深度搜索

    Given n, generate all structurally unique BST's (binary search trees) that store values 1...n. For e ...

  7. [leetcode]Unique Binary Search Trees II @ Python

    原题地址:https://oj.leetcode.com/problems/unique-binary-search-trees-ii/ 题意:接上一题,这题要求返回的是所有符合条件的二叉查找树,而上 ...

  8. LeetCode:Unique Binary Search Trees I II

    LeetCode:Unique Binary Search Trees Given n, how many structurally unique BST's (binary search trees ...

  9. [LeetCode] Unique Binary Search Trees 独一无二的二叉搜索树

    Given n, how many structurally unique BST's (binary search trees) that store values 1...n? For examp ...

随机推荐

  1. Android来电监听和去电监听

    我觉得写文章就得写得有用一些的,必须要有自己的思想,关于来电去电监听将按照下面三个问题展开 1.监听来电去电有什么用? 2.怎么监听,来电去电监听方式一样吗? 3.实战,有什么需要特别注意地方? 监听 ...

  2. .NET平台上插拔姿势的AOP

    AOP概述 AOP技术的诞生并不算晚,早在1990年开始,来自Xerox Palo Alto Research Lab(即PARC)的研究人员就对面向对象思想的局限性进行了分析.他们研究出了一种新的编 ...

  3. Java DNS查询内部实现

    源码分析 在Java中,DNS相关的操作都是通过通过InetAddress提供的API实现的.比如查询域名对应的IP地址: String dottedQuadIpAddress = InetAddre ...

  4. SSH中Action的单例与多例

    Structs2中的Bean默认的是单例,在整个程序运行期间,每个Bean只有一个实例,只要程序在运行,这个实例就一直存在. 对于Action来说,单例就容易出问题.如果客户端每次提交的参数都是一样的 ...

  5. 经典的一款jQuery soChange幻灯片

    soChange一款多很经典的幻灯片的jQuery插件. 实例预览 引入文件 <link rel="stylesheet" type="text/css" ...

  6. string.empty , "" , null 以及性能的比较

    一:这种结论,个人觉得仍然存疑 http://www.cnblogs.com/wangshuai901/archive/2012/05/06/2485657.html 1.null    null 关 ...

  7. htm常用标签总结

    1.结构性定义 文件类型 <HTML></HTML> (放在档案的开头与结尾) 文件主题 <TITLE></TITLE> (必须放在「文头」区块内) 文 ...

  8. JQ实现判断iPhone、Android设备

    最近做了一版微信宣传页,通过JQ来判断设备,并进行下载 微信内置浏览器对下载链接进行了屏蔽,所以先进行判断,如果是微信内置浏览器,则跳转应用宝链接,如果不是,则判断是iPhone/Adroid/PC ...

  9. KOTLIN开发语言文档(官方文档) -- 入门

    网页链接:https://kotlinlang.org/docs/reference/basic-syntax.html 1.   入门 1.1.  基本语法 1.1.1.   定义包 包说明应该在源 ...

  10. ViewPager轮播图

    LoopViewPagerLayout无限轮播 项目地址:https://github.com/why168/LoopViewPagerLayout 支持三种动画: 支持修改轮播的速度: 支持修改滑动 ...