LC每日一题|20240402 - 894. 所有可能的真二叉树

91 阅读2分钟

LC每日一题|20240402 - 894. 所有可能的真二叉树

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

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

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

提示:

  • 1 <= n <= 20

题目级别: Medium

这题已经给了真二叉树的定义,即树中每个节点恰好有 02 个子节点。

由于每个节点只能有 0 个或者 2 个子节点,所以对于一棵真二叉树,除了其根节点外,任意一层的节点数量一定是偶数个,整个树的节点数量一定是奇数个。此时我们可以对输入数据做一步预处理,即当 n 为偶数时,返回空数组。

同时该树的左子树右子树一定也满足该性质,显然, n = 当前节点 + 左子树节点数量 + 右子树节点数量,据此我们可以递归求取满足条件的左右子树,并拼接得到需要的结果。而其截止条件即是只有 1 个节点的情况,可以直接返回一个 [0]

作为优化,我们可以做一个记忆化搜索。但是这个数据范围非常小,所以不做优化也能轻松AC(但是最好还是要写一下的~)。

/**
 * Example:
 * var ti = TreeNode(5)
 * var v = ti.`val`
 * Definition for a binary tree node.
 * class TreeNode(var `val`: Int) {
 *     var left: TreeNode? = null
 *     var right: TreeNode? = null
 * }
 */
class Solution {
    val map = HashMap<Int, ArrayList<TreeNode>>()
    init { map[1] = arrayListOf(TreeNode(0)) }
    fun allPossibleFBT(n: Int): List<TreeNode?> {
        val res = ArrayList<TreeNode>()
        if (n == 1) return map[1]!!
        for (i in 1 until n - 1 step 2) {
            val j = n - 1 - i
            val left = map[i] ?: allPossibleFBT(i)
            val right = map[j] ?: allPossibleFBT(j)
            for (l in left) {
                for (r in right) {
                    val node = TreeNode(0)
                    node.left = l
                    node.right = r
                    res.add(node)
                }
            }
        }
        map[n] = res
        return res
    }
}