稀碎从零算法笔记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;
    }
};

结算页面

相关推荐
OTWOL23 分钟前
【C++编程入门基础(一)】
c++·算法
谏君之28 分钟前
C语言实现的常见算法示例
c语言·算法·排序算法
宇寒风暖1 小时前
侯捷 C++ 课程学习笔记:内存管理与工具应用
c++·笔记·学习
机器视觉知识推荐、就业指导1 小时前
【数字图像处理二】图像增强与空域处理
图像处理·人工智能·经验分享·算法·计算机视觉
云缘若仙1 小时前
directx12 3d+vs2022游戏开发第六章 笔记十一
笔记·directx12 3d
电棍2332 小时前
在wsl环境中配置和开发verilog(一种比较新颖的verilog开发指南)
笔记
IT猿手2 小时前
超多目标优化:基于导航变量的多目标粒子群优化算法(NMOPSO)的无人机三维路径规划,MATLAB代码
人工智能·算法·机器学习·matlab·无人机
Erik_LinX2 小时前
算法日记25:01背包(DFS->记忆化搜索->倒叙DP->顺序DP->空间优化)
算法·深度优先
Alidme2 小时前
cs106x-lecture14(Autumn 2017)-SPL实现
c++·学习·算法·codestepbystep·cs106x
小王努力学编程2 小时前
【算法与数据结构】单调队列
数据结构·c++·学习·算法·leetcode