生成不同的二叉树

题目描述

给你一个整数 n ,请你生成并返回所有由 n 个节点组成且节点值从 1 到 n 互不相同的不同 二叉搜索树 。可以按 任意顺序 返回答案。

思路:


二叉搜索树的特点是根节点大于左子树所有节点的值,小于右子树所有节点的值,且左右子树都满足该性质。
对于序列中任意一个值i,可以将区间分成两块,[1, i - 1],和[i + 1, n]。左子树和右子树的生成相较于原问题是序列长度缩小的子问题,因此可用递归法,且递归函数肯定包括区间的起点和终点。

递归函数:
vector<TreeNode*> generateTrees(start, end), 返回[start, end]区间内所有可行的二叉搜索树。

遍历顺序:
遍历[start, end]区间中的值i为当前根节点,递归调用[start, i - 1]和[i + 1, end]这两个区间,获得所有可行的左子树和右子树,最后从左子树集合选择一棵作为当前节点i的左子树,从右子树集合中选择一棵作为当前节点i的右子树,并且生成以当前节点i为根节点的树放入结果集合中即可。

终止条件:
递归的入口即为 generateTrees(1, n),出口为当 start>end 的时候,该区间没有数据,即当前二叉搜索树为空,返回空节点即可。

代码实现

/**
* 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:
    vector<TreeNode*> generateTrees(int start, int end){
        if(start > end){
            return vector<TreeNode*>{nullptr};
        }
        vector<TreeNode*> allTrees;  //每一层有一个数组,表示该层的所有可行二叉搜索树
        //枚举所有可行根节点
        for(int i = start; i <= end; i++){
            vector<TreeNode*> leftTrees = generateTrees(start, i - 1); // 获得所有可行的左子树集合
            vector<TreeNode*> rightTrees = generateTrees(i + 1, end);  // 获得所有可行的右子树集合

            //从左子树集合中选出一棵左子树,从右子树集合中选出一棵右子树,拼接到根节点上
            for(auto &it1 : leftTrees)
                for(auto &it2 :rightTrees){
                    TreeNode* root = new TreeNode(i);
                    root->left = it1;
                    root->right = it2;
                    allTrees.emplace_back(root);
                }
        }

        return allTrees;
    }

    vector<TreeNode*> generateTrees(int n) {
        if(!n){
            return vector<TreeNode*>{};
        }

        return generateTrees(1, n);
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值