95. 不同的二叉搜索树 II
给你一个整数 n ,请你生成并返回所有由 n 个节点组成且节点值从 1 到 n 互不相同的不同 二叉搜索树 。可以按 任意顺序 返回答案。
- 题目要求求出所有不同的二叉搜索树,要是以穷举的方式太过复杂,那么就要思考一下
解决子问题
的思想了 - 一个二叉搜索树由:
左子树
右子树
根节点
组成,通过观察示例,我们可以列举出根节点不同的所有情况,比如从 1 到 3,根节点就有可能是 1,2,3 - 然后考虑左子树与右子树,我们只需要将根节点的左指针指向左子树的头节点,右指针指向右子树的头节点即可,这样我们就转化成了求左子树跟右子树的问题
- 同理,子树也可以通过上述,分段的方式来求解,这就向着回溯算法去了。
举个例子:
从 1到4
- 首先我们要让1到4依次作为根节点
- 让1做根节点时:
- 1的左子树为null,右子树为2到4
- 此时问题转化为求2到4的排列。
- 而2到4可以分为2做头节点,3做头节点,4做头节点
- 2做头节点时,左子树为null右子树为3到4.。。。
代码示例
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
//find()的作用是找到从开始到结束的所有二叉搜索树
vector<TreeNode*> find(int start,int end)
{
//要是start比end要大,直接返回子树{nullptr}
//不能返回{},因为要使其指针指向这个数
//对应回溯之中的退出条件
if(start>end)
{
return {nullptr};
}
//创建ans数组来收集答案
vector<TreeNode*> ans;
//开始列举
for(int i=start;i<=end;i++)
{
//搜索左右子树并且记录下来
vector<TreeNode*> left=find(start,i-1);
vector<TreeNode*> right=find(i+1,end);
//穷举左右子树的所有情况并且记录
for(auto& l:left)
{
for(auto& r:right)
{
TreeNode* root=new TreeNode(i);
root->left=l;
root->right=r;
ans.push_back(root);
}
}
}
return ans;
}
vector<TreeNode*> generateTrees(int n) {
if(n==0)
{
return {};//当数字为0时返回空
}
else
{
return find(1,n);//否则返回从1,到4的所有树
}
}
};