稀碎从零算法笔记Day37-LeetCode:所有可能的真二叉树

今天的每日一题,感觉理解的还不够深,有待加深理解

题型:树、分治、递归

链接:894. 所有可能的真二叉树 - 力扣(LeetCode)

来源:LeetCode

题目描述

给你一个整数 n ,请你找出所有可能含 n 个节点的 真二叉树 ,并以列表形式返回。答案中每棵树的每个节点都必须符合 Node.val == 0

答案的每个元素都是一棵真二叉树的根节点。你可以按 任意顺序 返回最终的真二叉树列表**。**

真二叉树 是一类二叉树,树中每个节点恰好有 02 个子节点。(不一定是完全二叉树)

题目样例

示例 1:

复制代码
输入:n = 7
输出:[[0,0,0,null,null,0,0,null,null,0,0],[0,0,0,null,null,0,0,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,null,null,null,null,0,0],[0,0,0,0,0,null,null,0,0]]

示例 2:

复制代码
输入:n = 3
输出:[[0,0,0]]

提示:

  • 1 <= n <= 20

题目思路

真二叉树的定义能看明白,但如何枚举出来所有的情况不知道该如何实现

看了题解,发现了一种类似二叉树的先序遍历的枚举方法

讲方法之前先说一下真二叉树的特点:真二叉树的节点的度只能是0或2,那么其节点数只能是奇数 。然后真二叉树的子树,自然也是真二叉树,那么子树的节点数也是奇数。同时可以知道,真二叉树没将一个叶子节点变成非叶子,那么他就需要长出两个孩子------即多了1个叶子节点。推广可知:真二叉树的叶子数是【n+1/2】------其中n是节点数。

那么我们就知道了真二叉树的节点数。这样我们就能枚举左右子树分别有 i / n - i - 1 个节点的情况。创一个数组leftSon[i] 来表示左子树节点数为 i 的情况,那么对应的rightSon[i] 表示右子树的情况。

C++代码

cpp 复制代码
/**
 * 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:
    //每个节点的出度只能是 0 或者 2 
    // 真二叉树 节点数一定为奇数
    // 返回所有真二叉树的情况
    vector<TreeNode*> allPossibleFBT(int n) {
        vector<TreeNode *> ans;
        if(n % 2 == 0)
            return ans;
        // 只有一个节点 或者左/右子树只有一个节点,此时递归结束
        if(n == 1)
        {
            ans = {new TreeNode(0)};
            return ans;
        }
        // 节点数只能是奇数,左/右子树的节点数也得是奇数个
        for(int i = 1;i < n ; i += 2)
        {
            // 对左/右子树的所有节点个数枚举出来
            vector<TreeNode *>leftSon = allPossibleFBT(i);
            vector<TreeNode *> rightSon = allPossibleFBT(n-1-i);
            for(auto L : leftSon)
            {
                for(auto R : rightSon)
                {
                    ans.emplace_back(new TreeNode(0,L,R));
                    // ans.emplace_back(root);
                }
            }
        }
        return ans;
    }
};

结算页面

相关推荐
吱吱鼠叔几秒前
MATLAB计算与建模常见函数:5.曲线拟合
算法·机器学习·matlab
嵌入式AI的盲1 小时前
数组指针和指针数组
数据结构·算法
Indigo_code4 小时前
【数据结构】【顺序表算法】 删除特定值
数据结构·算法
__AtYou__4 小时前
Golang | Leetcode Golang题解之第448题找到所有数组中消失的数字
leetcode·golang·题解
阿史大杯茶4 小时前
Codeforces Round 976 (Div. 2 ABCDE题)视频讲解
数据结构·c++·算法
LluckyYH5 小时前
代码随想录Day 58|拓扑排序、dijkstra算法精讲,题目:软件构建、参加科学大会
算法·深度优先·动态规划·软件构建·图论·dfs
转调5 小时前
每日一练:地下城游戏
开发语言·c++·算法·leetcode
不穿格子衬衫5 小时前
常用排序算法(下)
c语言·开发语言·数据结构·算法·排序算法·八大排序
wdxylb5 小时前
使用C++的OpenSSL 库实现 AES 加密和解密文件
开发语言·c++·算法
aqua35357423585 小时前
蓝桥杯-财务管理
java·c语言·数据结构·算法