Given a perfect binary tree, populate each next
pointer to point to its next right node. If there is no next right node, the next
pointer should be set to NULL
.
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
Initially, all next
pointers are set to NULL
.
Example 1:
Input: root = [1,2,3,4,5,6,7]
Output: [1,#,2,3,#,4,5,6,7,#]
Explanation: Given the above perfect binary tree, your function should populate each next pointer to point to its next right node, just like in the output. The serialized output is in level order as connected by the next pointers, with '#' signifying the end of each level.
Example 2:
Input: root = []
Output: []
Constraints:
[0, 2^12 - 1]
-1000 <= Node.val <= 1000
Follow-up:
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force approach to connecting nodes at the same level in a tree involves examining every single node and, for each, exhaustively searching for the next node on the same level. It’s like manually checking every connection for each node without any shortcuts. It guarantees finding the solution but might take a lot of work.
Here's how the algorithm would work step-by-step:
def connect_brute_force(root):
if not root:
return root
all_nodes = []
def traverse(node):
if node:
all_nodes.append(node)
traverse(node.left)
traverse(node.right)
traverse(root)
for current_node in all_nodes:
next_right = None
min_distance = float('inf')
for potential_neighbor in all_nodes:
if current_node != potential_neighbor:
# Find nodes at same level
if get_level(root, current_node, 1) == get_level(root, potential_neighbor, 1):
distance = all_nodes.index(potential_neighbor) - all_nodes.index(current_node)
# Ensure next node is to the right
if distance > 0 and distance < min_distance:
min_distance = distance
next_right = potential_neighbor
current_node.next = next_right
return root
def get_level(root_node, target_node, level):
if not root_node:
return 0
if root_node == target_node:
return level
downlevel = get_level(root_node.left, target_node, level + 1)
if downlevel != 0:
return downlevel
downlevel = get_level(root_node.right, target_node, level + 1)
return downlevel
The key is to use the existing next-level connections to your advantage while traversing level by level. We use already established links to navigate and connect nodes on each level without needing extra memory.
Here's how the algorithm would work step-by-step:
class Node:
def __init__(self, val=0, left=None, right=None, next=None):
self.val = val
self.left = left
self.right = right
self.next = next
def connect(root):
if not root:
return root
head = root
while head:
current_node = head
next_level_head = None
previous_node = None
# Iterate through the current level
while current_node:
# Connect left child
if current_node.left:
if not next_level_head:
next_level_head = current_node.left
if previous_node:
previous_node.next = current_node.left
previous_node = current_node.left
# Connect right child
if current_node.right:
if not next_level_head:
next_level_head = current_node.right
if previous_node:
previous_node.next = current_node.right
previous_node = current_node.right
# Move to the next node on the current level
current_node = current_node.next
# Move to the next level
head = next_level_head
return root
Case | How to Handle |
---|---|
Null root node | Return null immediately, as there's nothing to connect. |
Single node tree | The next pointer of the root remains null, as there are no other nodes to connect to on the same level. |
Complete binary tree | The algorithm should correctly link all nodes on each level from left to right. |
Skewed tree (left or right) | The iterative level-order traversal must handle potentially missing child nodes on each level correctly. |
Tree with varying depths of subtrees | The level-order traversal ensures the algorithm links nodes on a level regardless of subtree depth differences. |
Tree with only left children present | The algorithm should correctly identify and link next nodes using the inner while loop conditions. |
Tree with only right children present | The algorithm should correctly identify and link next nodes using the inner while loop conditions. |
Large tree (memory constraints) | Level order traversal uses O(W) space where W is the maximum width of the tree; iterative solution is preferable to recursive for very deep trees. |