Description:
A full binary tree is a binary tree where each node has exactly 0 or 2 children.
Return a list of all possible full binary trees with N nodes. Each element of the answer is the root node of one possible tree.
Each node of each tree in the answer must have node.val = 0.
You may return the final list of trees in any order.
Example 1:
Note:
1 <= N <= 20
Analysis:
Firstly, we can get several inferences from the problem:
- If a tree is a full binary tree, then the amount of all its nodes must be odd because every node(except the root node) can be made a pair with another son node of its parent node( 2 ∗ p a i r N u m b e r + 1 2 * pairNumber + 1 2∗pairNumber+1).
- If a tree is a full binary tree, then its left subtree and right subtree(if exists) are also full binary trees, and the amount of nodes in each subtree is also odd.
Secondly, we use FBT(N) to denote a full binary tree with N nodes.
Then its left subtree and right subtree can be denoted as FBT(i) and FBT(N-1-i) respectively where i is an odd.
We can use a recursion to get a list of root nodes of FBT(i) and a list of root nodes of FBT(N-1-i) . Then do the combination of items in two lists to create a list of root nodes of FBT(N).
Code:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<TreeNode> allPossibleFBT(int N) {
List<TreeNode> list = new ArrayList<>();
if(N == 1) {
TreeNode node = new TreeNode(0);
list.add(node);
}else{
for(int i = 1; i <= N-2; i+=2) {
// a list of root nodes of left subtree
List<TreeNode> leftFBT = allPossibleFBT(i);
// a list of root nodes of right subtree
List<TreeNode> rightFBT = allPossibleFBT(N-1-i);
// do the combination
for(TreeNode l: leftFBT) {
for(TreeNode r: rightFBT) {
TreeNode root = new TreeNode(0);
root.left = l;
root.right = r;
list.add(root);
}
}
}
}
return list;
}
}
Tweak:
In the above solution, we may repeatedly calculate some results. For example, N = 7 is given, if the left subtree has 1 node and the right subtree has 5 nodes, we will calculate FBT(1) and FBT(5). However, with the progress of a loop, if the left subtree has 5 nodes and the right tree has 1 node we will repeatedly calculate FBT(5) and FBT(1). So we add a memory search strategy to our solution which uses a hash map to store the calculated results.
Code:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
Map<Integer, List<TreeNode>> memo = new HashMap<>(); // memory
public List<TreeNode> allPossibleFBT(int N) {
if(!memo.containsKey(N)) { // memory search
List<TreeNode> FBT = new ArrayList<>();
if(N == 1) {
TreeNode node = new TreeNode(0);
FBT.add(node);
}else{
for(int i = 1; i <= N-2; i+=2) {
// a list of root nodes of left subtree
List<TreeNode> leftFBT = allPossibleFBT(i);
// a list of root nodes of right subtree
List<TreeNode> rightFBT = allPossibleFBT(N-1-i);
// do the combination
for(TreeNode l: leftFBT) {
for(TreeNode r: rightFBT ) {
TreeNode root = new TreeNode(0);
root.left = l;
root.right = r;
FBT.add(root);
}
}
}
}
memo.put(N, FBT); // add the calculated result to the memory
return FBT;
}else{
return memo.get(N);
}
}
}