
Problem Statement
In the context of binary trees, a complete binary tree is defined as one in which every level—except possibly the last—is completely filled, and all nodes are as far left as possible.
Your task is to design a class CBTInserter
that:
- Initializes with the root of an existing complete binary tree.
- Allows inserting new nodes while maintaining the completeness property.
- Provides access to the current root node.
The operations to implement include:
CBTInserter(TreeNode root)
– Initializes the data structure with the given root.int insert(int val)
– Inserts a new node with valueval
in a way that maintains tree completeness. Returns the value of the parent node to which the new node was added.TreeNode get_root()
– Returns the root node of the tree after all insertions.
Examples
Example 1
Input:
["CBTInserter", "insert", "insert", "get_root"] [[[1, 2]], [3], [4], []]
Output:
[null, 1, 2, [1, 2, 3, 4]]
Explanation:
CBTInserter cBTInserter = new CBTInserter([1, 2]);
Initializes the tree with root1
and left child2
.cBTInserter.insert(3);
➜ returns1
Adds3
as the right child of node1
.cBTInserter.insert(4);
➜ returns2
Adds4
as the left child of node2
.cBTInserter.get_root();
➜ returns[1, 2, 3, 4]
Returns the updated tree in level order.
Constraints
- The number of nodes in the tree is in the range
[1, 1000]
. 0 <= Node.val <= 5000
0 <= val <= 5000
- The initial
root
is a complete binary tree. - At most
10⁴
calls will be made toinsert
andget_root
.
Approach and Intuition
Maintaining completeness during insertions requires identifying the next available position in level order (left to right, top to bottom). A queue makes this efficient.
Key Ideas
Track Incomplete Nodes:
- Use a queue to store nodes that are missing at least one child.
- Always insert new nodes as children of the node at the front of the queue.
Insert Operation:
- Peek the front node of the queue.
- If it has no left child, insert there.
- Otherwise, insert at the right.
- If the node now has both children, remove it from the queue.
- Enqueue the newly added node (it may receive children later).
- Return the value of the parent node.
Get Root Operation:
- Return the root node stored during initialization.
Why This Works
- This approach guarantees O(1) access to the next insertion point using the queue.
- It ensures each level is filled from left to right.
- Space complexity is O(n) for storing the tree and queue references.
Example Detailed Walkthrough
- Initial tree:
[1, 2]
. Node1
has left child2
. - Insert
3
: Node1
gets3
as right child. Now both its children are filled, so it's removed from the queue. - Insert
4
: Node2
gets4
as left child. - Final tree structure (level order):
[1, 2, 3, 4]
.
This method leverages BFS and a queue to ensure that insertions always respect the structure of a complete binary tree.
Solutions
- Java
class CompleteBinaryTreeInserter {
TreeNode rootNode;
Deque<TreeNode> nodeDeque;
public CompleteBinaryTreeInserter(TreeNode rootNode) {
this.rootNode = rootNode;
nodeDeque = new ArrayDeque<>();
Queue<TreeNode> bfsQueue = new ArrayDeque<>();
bfsQueue.offer(rootNode);
while (!bfsQueue.isEmpty()) {
TreeNode currentNode = bfsQueue.poll();
if (currentNode.left == null || currentNode.right == null)
nodeDeque.offerLast(currentNode);
if (currentNode.left != null)
bfsQueue.offer(currentNode.left);
if (currentNode.right != null)
bfsQueue.offer(currentNode.right);
}
}
public int insert(int value) {
TreeNode newNode = new TreeNode(value);
TreeNode parentNode = nodeDeque.peekFirst();
nodeDeque.offerLast(newNode);
if (parentNode.left == null)
parentNode.left = newNode;
else {
parentNode.right = newNode;
nodeDeque.pollFirst();
}
return parentNode.val;
}
public TreeNode getRoot() {
return rootNode;
}
}
This solution implements a class named CompleteBinaryTreeInserter
for managing the insertion of nodes into a complete binary tree in Java. The class uses a TreeNode
for the tree structure and maintains the nodes in a level-order fashion using Java's Deque
and Queue
interfaces.
Initialize an instance with an existing root node. During initialization, the constructor leverages breadth-first search (BFS) to populate a
Deque
(nodeDeque
), helping to track where the next child node will be inserted. Nodes that may still accept new children (nodes missing either left or right child) are added tonodeDeque
.The
insert
method adds a new node with a specified value into the tree. It retrieves the first node innodeDeque
that requires a new child and attaches the new node appropriately as either a left or right child. If a node receives a new right child, it's deemed complete and removed fromnodeDeque
. The value of the parent node is returned after the insertion.The
getRoot
method simply returns the root of the current tree.
This structure ensures efficient node insertions while maintaining the complete binary tree characteristics: each level of the tree is filled entirely before moving on to a new level, and each new node is inserted at the leftmost available position at the bottom level.
No comments yet.