0x00 题目
满二叉树是一类二叉树
其中每个节点恰好有 0 或 2 个子节点
返回包含 N 个节点的所有可能满二叉树的列表
答案的每个元素都是一个可能树的根节点
答案中每个树的每个节点都必须有 node.val = 0
你可以按任何顺序返回树的最终列表
0x01 思路
每个节点恰好有 0 或 2 个子节点
那么加上当前节点
总共是 1 或 3 个节点
所以子节点也只能是 1 个 或 3 个
进而推断出,只有奇数个时
才能构成满二叉树
由于每个元素都是一个可能树的根节点
以 i 为根节点,则
0 到 i-1 构成左子树
i+1 到 N-1 构成右子树
左右子树也是满二叉树
于是原问题变成了更小规模的问题
使用递归来解决
0x02 解法
语言:Swift
树节点:TreeNode
public class TreeNode {
public var val: Int
public var left: TreeNode?
public var right: TreeNode?
public init() { self.val = 0; self.left = nil; self.right = nil; }
public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; }
public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) {
self.val = val
self.left = left
self.right = right
}
}
解法:
func allPossibleFBT(_ n: Int) -> [TreeNode?] {
// 构建过程中,递归存在重复计算,缓存结果
var cache: [Int:[TreeNode?]] = [:]
func build(_ n: Int) -> [TreeNode?] {
if n == 0 { return [] }
if n == 1 { return [TreeNode(0)] }
var res: [TreeNode?] = []
var i = 1
while i < n - 1 {
// 左子树集合
var leftTrees = cache[i]
if leftTrees == nil {
leftTrees = build(i)
}
// 右子树集合
var rightTrees = cache[n-i-1]
if rightTrees == nil {
rightTrees = build(n-i-1)
}
// 分别从左子树集合中,右子树集合中,拿出一棵子树,组成一棵完整的树
for left in 0..<leftTrees!.count {
for right in 0..<rightTrees!.count {
let node = TreeNode(0)
node.left = leftTrees![left]
node.right = rightTrees![right]
res.append(node)
}
}
// 偶数个时,无法构建满二叉树,所以遍历奇数
i += 2
}
cache[n] = res
return res
}
let res = build(n)
return res
}
0x03 我的小作品
欢迎体验我的作品之一:小汉字-XHanzi
汉字书写入门,常用汉字 3800 个,二级字表 2200 个
App Store 搜索即可~