
Problem Statement
In this problem, we are tasked with connecting the next
pointers of a perfect binary tree such that each node's next
pointer points to its immediate right sibling on the same level. If a node is the last one on its level, its next
pointer should point to NULL
.
A perfect binary tree is defined as a binary tree where:
- All interior nodes have two children.
- All leaf nodes are at the same level.
Each node in the tree has the following structure:
val
: The integer value of the nodeleft
: Pointer to the left childright
: Pointer to the right childnext
: Pointer to the next right node (initiallyNULL
)
The challenge is to connect all next
pointers correctly without using additional data structures like queues or arrays for level-order traversal.
Examples
Example 1
Input:
root = [1,2,3,4,5,6,7]
Output:
[1,#,2,3,#,4,5,6,7,#]
Explanation:
After connecting, the `next` pointers link nodes level by level: Level 0: 1 → # Level 1: 2 → 3 → # Level 2: 4 → 5 → 6 → 7 → # This output is serialized in level order with '#' indicating the end of a level.
Example 2
Input:
root = []
Output:
[]
Explanation:
The tree is empty, so there are no nodes to connect.
Constraints
- The number of nodes in the tree is in the range
[0, 2^12 - 1]
-1000 <= Node.val <= 1000
Approach and Intuition
To solve this problem efficiently, we take advantage of the perfect binary tree structure. The key ideas are:
Start from the root:
- If the root is
NULL
, return immediately.
- If the root is
Traverse level by level without extra space:
- Use the leftmost node of each level to move to the next level.
- Use the
next
pointers established in the current level to traverse horizontally.
For each node at a level:
- Connect its
left
child’snext
to itsright
child. - If the node has a
next
pointer (i.e., it's not the last node on that level), connect itsright
child’snext
to the left child of the node'snext
.
- Connect its
Repeat until you reach the last level:
- Move to the leftmost node’s left child at each level.
This in-place level-wise connection avoids using any queues or additional data structures and works in O(1) extra space, leveraging the next
pointers to traverse horizontally across each level.
Solutions
- C++
- Java
- C
- JavaScript
- Python
class Solution {
public:
Node* connectNodes(Node* root) {
if (!root) {
return root;
}
Node* currentLevelStart = root;
while (currentLevelStart->left) {
Node* currentNode = currentLevelStart;
while (currentNode) {
currentNode->left->next = currentNode->right;
if (currentNode->next) {
currentNode->right->next = currentNode->next->left;
}
currentNode = currentNode->next;
}
currentLevelStart = currentLevelStart->left;
}
return root;
}
};
The solution presented connects 'next' right pointers in each node of a perfect binary tree using a level order traversal process. The function connectNodes
takes the root of the binary tree as an input parameter and ensures that each node is modified so that its next
pointer points to its right adjacent node in the same level.
To achieve this:
- Check if the
root
is null. If true, return the root immediately as there is nothing to process. - Initialize a pointer,
currentLevelStart
, to keep track of the first node of each level, starting with the root. - Use a while loop to iterate through each level of the tree as long as the current level’s start node has a left child.
- Inside the loop, use another pointer
currentNode
starting fromcurrentLevelStart
to iterate through the nodes in the current level.- Set the
next
pointer of the left child of the current node to point to the right child of the same node. - If the current node has a next node, then set the
next
pointer of the right child of the current node to the left child of the next node. - Move to the next node by updating
currentNode
tocurrentNode->next
.
- Set the
- Once the inner while loop finishes, move to the next level by setting
currentLevelStart
to the left child of the current level’s start node. - Continue the process until all levels are linked correctly.
- Finally, return the modified
root
.
This approach leverages the structure of a perfect binary tree where every parent node has two children, efficiently linking each node to the adjacent node at the same level without additional space for recursion or a queue.
class Solution {
public Node connectRight(Node root) {
if (root == null) {
return root;
}
Node current = root;
while (current.left != null) {
Node temp = current;
while (temp != null) {
temp.left.next = temp.right;
if (temp.next != null) {
temp.right.next = temp.next.left;
}
temp = temp.next;
}
current = current.left;
}
return root;
}
}
The code provided effectively links each node in a perfect binary tree with its adjacent right node using a next pointer. This connection process in Java requires traversing the tree level-by-level.
- Begin with the root node. If the root is null, immediately return the root since no connections can be made.
- Utilize two while loops to navigate the tree:
- The outer loop moves from top to bottom (level by level), starting at the root.
- The inner loop progresses node by node within the same level, starting from the leftmost node of each level.
- In the inner loop:
- Connect the left child (
left.next
) to the right child (right
) of the same node. - If there’s a next node at the same level (
temp.next
), connect the right child of the current node to the left child of the next node (temp.right.next = temp.next.left
).
- Connect the left child (
- Continue this pattern until all levels of the tree have been connected.
- Finally, return the modified root, which now possesses next right pointers for each node.
This approach ensures that each node's next
right pointers are set without using additional storage, operating directly on the tree structure.
struct Node* link_nodes(struct Node* root_node) {
if (root_node == NULL) {
return root_node;
}
struct Node* level_start = root_node;
while (level_start->left != NULL) {
struct Node* current = level_start;
while (current != NULL) {
current->left->next = current->right;
if (current->next != NULL) {
current->right->next = current->next->left;
}
current = current->next;
}
level_start = level_start->left;
}
return root_node;
}
The C function link_nodes
aims to connect the next
pointers in a binary tree, where each node points to its next right node at the same level. If no right node exists, the next pointer should point to NULL
.
Begin by checking if the
root_node
isNULL
. If it is, return immediately as there are no nodes to link.Initialize
level_start
toroot_node
. This variable tracks the start of each level in the binary tree.Use an outer
while
loop that continues as long as there are left children. This indicates that the tree has more levels to process.Within this loop, initialize
current
tolevel_start
. Use this to traverse nodes across the current level.For each node processed in the inner loop:
- Link the left child's
next
pointer to the right child. - If there exists a
next
node forcurrent
, link the right child'snext
pointer to the left child of thenext
node.
- Link the left child's
Move
current
to the next node at the same level (i.e.,current->next
).After finishing linking nodes at the current level, move
level_start
down to the next level by setting it to the left child of the currentlevel_start
.The function returns the modified
root_node
, now with appropriately setnext
pointers across all levels.
This approach is efficient as it only uses constant extra space and processes nodes level by level, ensuring all next
pointers are configured before moving to a deeper level.
var linkNodes = function (node) {
if (node === null) {
return node;
}
let currentLevelStart = node;
while (currentLevelStart.left !== null) {
let currentNode = currentLevelStart;
while (currentNode !== null) {
currentNode.left.next = currentNode.right;
if (currentNode.next !== null) {
currentNode.right.next = currentNode.next.left;
}
currentNode = currentNode.next;
}
currentLevelStart = currentLevelStart.left;
}
return node;
};
The provided JavaScript function, linkNodes
, is designed to connect the next right pointers for each node in a perfect binary tree. Perfect binary trees are those where every internal node has exactly two children and all leaf nodes are at the same level.
The function takes a
node
as its argument which represents the root of the binary tree. If the root node isnull
, the function immediately returns it, handling the edge case where the input tree is empty.The function uses two nested while loops:
- The outer loop manages the levels of the tree, starting from the root. It keeps track of the start of the current level using the variable
currentLevelStart
. - The inner loop iterates through the nodes at the current level. It uses the variable
currentNode
for navigation.
- The outer loop manages the levels of the tree, starting from the root. It keeps track of the start of the current level using the variable
Within the inner loop, the function links the
next
pointer of the current node's left child to its right child (currentNode.left.next = currentNode.right
).Furthermore, if the current node has a neighbor (i.e.,
currentNode.next
is not null), the function links thenext
pointer of the current node's right child to the left child of the next node (currentNode.right.next = currentNode.next.left
). This establishes the horizontal connections between nodes that are not direct siblings but neighbors across parent nodes.After completing the connections for one level, the outer loop moves to the next level by setting
currentLevelStart
to the left child of the current level start.The function finally returns the modified root node with all next pointers set accordingly, effectively populating the next right pointers for each node in the provided tree.
This approach ensures that every node's next pointer either points to its adjacent right node at the same level or remains null
if it is the rightmost node at its level. This function operates in linear time complexity, O(N), where N is the number of nodes in the tree, as it visits each node exactly once.
class Solution:
def populateNextPointers(self, root: "Node") -> "Node":
if not root:
return root
lead = root
while lead.left:
currentNode = lead
while currentNode:
currentNode.left.next = currentNode.right
if currentNode.next:
currentNode.right.next = currentNode.next.left
currentNode = currentNode.next
lead = lead.left
return root
This solution tackles the problem of populating each node in a perfect binary tree with its next right node pointer. The idea is to connect all nodes on the same level from left to right in constant additional space, not counting the space required for the output.
The code implements a function populateNextPointers
that accepts the root of the binary tree and returns the root after modifying the tree. The function operates as follows:
- Start by checking if the root is
None
. If true, return the root since there's nothing to process. - Initialize the
lead
variable to keep track of the leftmost node of the current level, starting with the root. - Use a nested loop to traverse through the levels and the nodes on each level. The outer loop moves down the levels starting from the root, and the inner loop traverses nodes on the same level.
- For each node denoted by
currentNode
, set thenext
pointer of its left child to its right child. - If the
currentNode
has a neighboring node to the right (currentNode.next
), link the right child of thecurrentNode
to the left child of this next node. - Move to the next node in the current level using
currentNode.next
. - After finishing with one level, move to the leftmost node of the next level using
lead.left
to continue the process for the next lower level. - The final tree, with next pointers appropriately populated, is returned.
This method ensures that each tree node points to its immediate right neighbor using no extra space, efficiently traversing levels and nodes within that level while updating connections based on the given structure and potential connections in an intuitive manner.
No comments yet.