Given an integer n
, return a list of all possible full binary trees with n
nodes. Each node of each tree in the answer must have Node.val == 0
.
Each element of the answer is the root node of one possible tree. You may return the final list of trees in any order.
A full binary tree is a binary tree where each node has exactly 0
or 2
children.
For example:
Example 1:
Input: n = 7
Output: [[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]]
Example 2:
Input: n = 3
Output: [[0,0,0]]
Constraints:
1 <= n <= 20
A brute-force approach would involve generating all possible binary trees with n
nodes and then filtering out the ones that are not full binary trees. However, this is highly inefficient as the number of possible binary trees grows exponentially with n
.
A more efficient approach involves using recursion and dynamic programming. The key idea is that a full binary tree with n
nodes can be constructed by combining smaller full binary trees. Specifically, for a full binary tree with n
nodes, the root node has two subtrees. If the left subtree has i
nodes, then the right subtree must have n - 1 - i
nodes (where 1 is subtracted for the root node itself). Both subtrees must also be full binary trees.
We can use memoization to store the results of subproblems and avoid recomputation.
Algorithm:
allPossibleFBT(n)
that returns a list of all possible full binary trees with n
nodes.n
is even, return an empty list because a full binary tree must have an odd number of nodes.n
is 1, return a list containing a single node with value 0.n
is already memoized, return it.i
, from 1 to n - 1
with a step of 2 (since the left subtree must also have an odd number of nodes).i
, recursively generate all possible left subtrees with i
nodes and all possible right subtrees with n - 1 - i
nodes.n
and return it.Code (Python):
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[TreeNode]:
memo = {}
def helper(n):
if n in memo:
return memo[n]
if n % 2 == 0:
return []
if n == 1:
return [TreeNode(0)]
res = []
for i in range(1, n, 2):
left_trees = helper(i)
right_trees = helper(n - 1 - i)
for left in left_trees:
for right in right_trees:
root = TreeNode(0)
root.left = left
root.right = right
res.append(root)
memo[n] = res
return res
return helper(n)
n
is even, there are no full binary trees, so return an empty list.n
is 1, there is only one full binary tree, which is a single node.memo
dictionary, and the maximum size of the memo
dictionary is proportional to the number of full binary trees.