分治dp,LeetCode 894. 所有可能的真二叉树

2024-04-02 14:36

本文主要是介绍分治dp,LeetCode 894. 所有可能的真二叉树,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

一、题目

1、题目描述

2、接口描述

​cpp

python3

3、原题链接

二、解题报告

1、思路分析

F1 回溯

F2 动态规划

2、复杂度

3、代码详解

​分治

cpp

python3

dp

cpp

python3


一、题目

1、题目描述

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

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

真二叉树 是一类二叉树,树中每个节点恰好有 0 或 2 个子节点。

2、接口描述

​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:vector<TreeNode*> allPossibleFBT(int n) {}
};
python3
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:def allPossibleFBT(self, n: int) -> List[Optional[TreeNode]]:

3、原题链接

894. 所有可能的真二叉树


二、解题报告

1、思路分析

F1 回溯

首先对于偶数个节点的情况直接返回空即可

然后分析,对于n(n为奇数)个节点的二叉树,根节点占一个节点,那么其左右节点的情况为

<1, n - 2>, <3, n - 4>……

所以我们发现构造n个节点的真二叉树可以分治为构造两个子真二叉树的问题

所以我们枚举左右儿子的节点数目进行分治构造即可

F2 动态规划

我们可以换种思路,自底向上分析

对于n个节点的真二叉树可以分为根节点加上两个子真二叉树

同样的,我们也可以由两个子真二叉树构造出一棵真二叉树

我们设f[k](k >= 1)为n = 2 * k - 1个节点的真二叉树的所有可能序列

那么f[i] = node(f[k], f[i - k]),这个递推还是比较简单的

相较于分治的做法,时间复杂度并未降低,但是省去了递归开销 

由于数据量只到20,因此我们可以预处理出f[1]~f[10]

2、复杂度

分治:时间复杂度:O(\frac{4_{}^{n}}{n_{}^{3/2}}) 空间复杂度:O(\frac{4_{}^{n}}{n_{}^{3/2}})

dp:预处理时间复杂度O(\frac{4_{}^{N}}{N_{}^{3/2}})预处理空间复杂度:O(\frac{4_{}^{N}}{N_{}^{3/2}}),N = 11

查询的时间复杂度和空间复杂度都是O(1)

3、代码详解

​分治
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:vector<TreeNode*> allPossibleFBT(int n) {vector<TreeNode*> ret;if(n % 2 == 0) return ret;if(n == 1) return {new TreeNode(0)};for(int i = 1; i < n; i += 2){vector<TreeNode*> leftnodes(allPossibleFBT(i)), rightnodes(allPossibleFBT(n - i - 1));for(TreeNode* x : leftnodes)for(TreeNode* y : rightnodes)ret.emplace_back(new TreeNode(0, x, y));}return ret;}
};
python3
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:def allPossibleFBT(self, n: int) -> List[Optional[TreeNode]]:if n % 2 == 0:return []if n == 1:return [TreeNode()]ret = []for i in range(1, n, 2):leftnodes, rightnodes = self.allPossibleFBT(i), self.allPossibleFBT(n - i - 1)ret.extend([TreeNode(0, x, y) for x in leftnodes for y in rightnodes])return ret

python也可以记忆化搜索,得到和dp相媲美的效率

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:@cachedef allPossibleFBT(self, n: int) -> List[Optional[TreeNode]]:if n % 2 == 0:return []if n == 1:return [TreeNode()]ret = []for i in range(1, n, 2):leftnodes, rightnodes = self.allPossibleFBT(i), self.allPossibleFBT(n - i - 1)ret.extend([TreeNode(0, x, y) for x in leftnodes for y in rightnodes])return ret

dp
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) {}* };*/
vector<TreeNode*> f[11];
bool init = []{f[1] = { new TreeNode() };for(int i = 2; i < 11; i++)for(int j = 1; j < i; j++)for(TreeNode* x : f[j])for(TreeNode* y : f[i - j])f[i].emplace_back(new TreeNode(0, x, y));return false;
}();
class Solution {
public:vector<TreeNode*> allPossibleFBT(int n) {return f[n & 1 ? (n + 1) / 2 : 0];}
};
python3
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
f = [[] for _ in range(11)]
f[1] = [TreeNode()]
for i in range(2, 11):f[i] = [TreeNode(0, x, y) for j in range(1, i)for x in f[j]for y in f[i - j]]
class Solution:def allPossibleFBT(self, n: int) -> List[Optional[TreeNode]]:return f[(n + 1) // 2] if n & 1 else []

这篇关于分治dp,LeetCode 894. 所有可能的真二叉树的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/870240

相关文章

MySQL中动态生成SQL语句去掉所有字段的空格的操作方法

《MySQL中动态生成SQL语句去掉所有字段的空格的操作方法》在数据库管理过程中,我们常常会遇到需要对表中字段进行清洗和整理的情况,本文将详细介绍如何在MySQL中动态生成SQL语句来去掉所有字段的空... 目录在mysql中动态生成SQL语句去掉所有字段的空格准备工作原理分析动态生成SQL语句在MySQL

浅谈mysql的sql_mode可能会限制你的查询

《浅谈mysql的sql_mode可能会限制你的查询》本文主要介绍了浅谈mysql的sql_mode可能会限制你的查询,这个问题主要说明的是,我们写的sql查询语句违背了聚合函数groupby的规则... 目录场景:问题描述原因分析:解决方案:第一种:修改后,只有当前生效,若是mysql服务重启,就会失效;

Python实现将MySQL中所有表的数据都导出为CSV文件并压缩

《Python实现将MySQL中所有表的数据都导出为CSV文件并压缩》这篇文章主要为大家详细介绍了如何使用Python将MySQL数据库中所有表的数据都导出为CSV文件到一个目录,并压缩为zip文件到... python将mysql数据库中所有表的数据都导出为CSV文件到一个目录,并压缩为zip文件到另一个

利用Go语言开发文件操作工具轻松处理所有文件

《利用Go语言开发文件操作工具轻松处理所有文件》在后端开发中,文件操作是一个非常常见但又容易出错的场景,本文小编要向大家介绍一个强大的Go语言文件操作工具库,它能帮你轻松处理各种文件操作场景... 目录为什么需要这个工具?核心功能详解1. 文件/目录存javascript在性检查2. 批量创建目录3. 文件

使用Navicat工具比对两个数据库所有表结构的差异案例详解

《使用Navicat工具比对两个数据库所有表结构的差异案例详解》:本文主要介绍如何使用Navicat工具对比两个数据库test_old和test_new,并生成相应的DDLSQL语句,以便将te... 目录概要案例一、如图两个数据库test_old和test_new进行比较:二、开始比较总结概要公司存在多

在MyBatis的XML映射文件中<trim>元素所有场景下的完整使用示例代码

《在MyBatis的XML映射文件中<trim>元素所有场景下的完整使用示例代码》在MyBatis的XML映射文件中,trim元素用于动态添加SQL语句的一部分,处理前缀、后缀及多余的逗号或连接符,示... 在MyBATis的XML映射文件中,<trim>元素用于动态地添加SQL语句的一部分,例如SET或W

C#实现获得某个枚举的所有名称

《C#实现获得某个枚举的所有名称》这篇文章主要为大家详细介绍了C#如何实现获得某个枚举的所有名称,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以参考一下... C#中获得某个枚举的所有名称using System;using System.Collections.Generic;usi

通过C#获取PDF中指定文本或所有文本的字体信息

《通过C#获取PDF中指定文本或所有文本的字体信息》在设计和出版行业中,字体的选择和使用对最终作品的质量有着重要影响,然而,有时我们可能会遇到包含未知字体的PDF文件,这使得我们无法准确地复制或修改文... 目录引言C# 获取PDF中指定文本的字体信息C# 获取PDF文档中用到的所有字体信息引言在设计和出

哈希leetcode-1

目录 1前言 2.例题  2.1两数之和 2.2判断是否互为字符重排 2.3存在重复元素1 2.4存在重复元素2 2.5字母异位词分组 1前言 哈希表主要是适合于快速查找某个元素(O(1)) 当我们要频繁的查找某个元素,第一哈希表O(1),第二,二分O(log n) 一般可以分为语言自带的容器哈希和用数组模拟的简易哈希。 最简单的比如数组模拟字符存储,只要开26个c

hdu4826(三维DP)

这是一个百度之星的资格赛第四题 题目链接:http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1004&cid=500 题意:从左上角的点到右上角的点,每个点只能走一遍,走的方向有三个:向上,向下,向右,求最大值。 咋一看像搜索题,先暴搜,TLE,然后剪枝,还是TLE.然后我就改方法,用DP来做,这题和普通dp相比,多个个向上