关于某种二叉树的生成

本文深入探讨了二叉树的生成与遍历问题,包括满二叉树和二叉搜索树的创建方法。通过递归算法,详细解析了如何生成所有可能的满二叉树和由1至n构成的不同二叉搜索树。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

引言:

最近在刷题过程中,二叉树的题还是相对来说比较简单的。那是因为二叉树的各类题型都是相关的,都是有迹可循。在二叉树的各种遍历是最简单的,而我在刷题过程中却碰到了一些二叉树的生成,看到题意后感觉无从下手,所以我就写下这篇文章来加深自己对这类题的印象。

题目1:所有可能的满二叉树

题目链接
**题目描述:**满二叉树是一类二叉树,其中每个结点恰好有 0 或 2 个子结点。返回包含 N 个结点的所有可能满二叉树的列表。 答案的每个元素都是一个可能树的根结点。答案中每个树的每个结点都必须有 node.val=0。你可以按任何顺序返回树的最终列表。
输入输出:
在这里插入图片描述

题解:

首先看到二叉树的题,就要有一种意识,那就是考虑递归(除非层次遍历相关的题)。然后再考虑二叉树的性质。满二叉树的节点数必须是奇数,否则无法构成。并且它的左右子树也要是满二叉树。
左子树的节点数可以是1,3,5,…,N-2;右子树的相应的节点数就是N-2,…,5,3,1.所以递归的生成左右子树,然后让根节点连接左子树的各种情况,和右子树相应的各种情况即可。保存每种情况,然后返回即可。

代码:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<TreeNode*> help(int N)
    {
        vector<TreeNode*> ve;
        if(N%2==0) return ve;
        if(N==1){
            TreeNode *t=new TreeNode(0);
            ve.push_back(t);
            return ve;
        }
        for(int i=1;i<N;i+=2)//i+=2保证左右子树0的个数为奇数
        {
            vector<TreeNode*> left=help(i);   //建立有i个的左子树,也是满二叉树
            vector<TreeNode*> right=help(N-1-i);  //建立有N-1-i个的右子树,也是满二叉树
            for(TreeNode* l:left)
                for(TreeNode* r:right){
                    TreeNode* t=new TreeNode(0); //以t为根,左子树为left的各种可能,右子树是right的各种可能
                    t->left=l;
                    t->right=r;
                    ve.push_back(t);
                }
        }
        return ve;
    }
    vector<TreeNode*> allPossibleFBT(int N) {
        return help(N);
    }
};

题目2:不同的二叉搜索树

题目链接
题目描述:
给定一个整数 n,生成所有由 1 … n 为节点所组成的二叉搜索树。
输入输出:
在这里插入图片描述

题解:

这一题和上一题相似,差不多就可以说一模一样了,可以使用相同的模板。这不过二叉树的性质不同了.但是只要找出二叉树性质的特点就不难写出此题。上一题的性质上面已经说清楚了,而这一题二叉树的性质就是①根节点的值大于左子树各结点的值,小于右子树各节点的值,②还有就是左右子树也必须是二叉搜索树。而此题的各节点的值是1,2,3,…,n.只要保证先确定一点为根节点的值,然后小于该点的各数建立左子树,大于该点的各数建立右子树,天然的保证了此题二叉搜索树的性质。所以只需遍历1到n,让该处的值作为根节点的值,左子树取遍各种左子树集合中的各值,右子树取遍各种右子树集合中的各值,然后一组合即可。最后把组合的情况保存起来并返回即可。

代码:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<TreeNode*> help(int L,int R)
    {
        vector<TreeNode*> ve;
        if(L>R){
            ve.push_back(NULL);
            return ve;
        }
        for(int i=L;i<=R;i++)
        {
            vector<TreeNode*> left_nodes=help(L,i-1); //从L到i-1生成一个二叉搜索树 
            vector<TreeNode*> right_nodes=help(i+1,R); //从i+1到R生成一个二叉搜索树 
            for(TreeNode* left_node :left_nodes)
                for(TreeNode* right_node:right_nodes)
                {
                    TreeNode *t=new TreeNode(i);//然后让i为根左子树是L到i-1的二叉搜索树右子树是 i+1到R的二叉搜索树
                    t->left=left_node;
                    t->right=right_node;
                    ve.push_back(t);
                }
        }
        return ve;
    }
    vector<TreeNode*> generateTrees(int n) {
        if(n==0)  return vector<TreeNode*> {};
        return help(1,n);
    }
};

结尾:

二叉树的题相对来说是比较容易的,只要每一类题(创建、遍历等)都有深刻的理解,那么做二叉树的题应该就没什么问题了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值