"""
# Definition for a Node.
class Node:
def __init__(self, val: int = 0, left: 'Node' = None, right: 'Node' = None, next: 'Node' = None):
self.val = val
self.left = left
self.right = right
self.next = next
class Solution:
def connect(self, root: 'Node') -> 'Node':
if not root:
return None
leftmost = root
while leftmost.left:
head = leftmost
while head:
head.left.next = head.right
if head.next:
head.right.next = head.next.left
head = head.next
leftmost = leftmost.left
return root
/*
// Definition for a Node.
class Node {
public:
int val;
Node* left;
Node* right;
Node* next;
Node() : val(0), left(NULL), right(NULL), next(NULL) {}
Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}
Node(int _val, Node* _left, Node* _right, Node* _next)
: val(_val), left(_left), right(_right), next(_next) {}
};
*/
class Solution {
public:
Node* connect(Node* root) {
if (!root) return nullptr;
Node* leftmost = root;
while (leftmost->left) {
Node* head = leftmost;
while (head) {
head->left->next = head->right;
if (head->next)
head->right->next = head->next->left;
head = head->next;
}
leftmost = leftmost->left;
}
return root;
}
};
/*
// Definition for a Node.
class Node {
public int val;
public Node left;
public Node right;
public Node next;
public Node() {}
public Node(int val) { this.val = val; }
public Node(int val, Node left, Node right, Node next) {
this.val = val;
this.left = left;
this.right = right;
this.next = next;
}
}
*/
class Solution {
public Node connect(Node root) {
if (root == null) return null;
Node leftmost = root;
while (leftmost.left != null) {
Node head = leftmost;
while (head != null) {
head.left.next = head.right;
if (head.next != null)
head.right.next = head.next.left;
head = head.next;
}
leftmost = leftmost.left;
}
return root;
}
}
/**
* // Definition for a Node.
* function Node(val, left, right, next) {
* this.val = val === undefined ? 0 : val;
* this.left = left === undefined ? null : left;
* this.right = right === undefined ? null : right;
* this.next = next === undefined ? null : next;
* };
*/
/**
* @param {Node} root
* @return {Node}
*/
var connect = function(root) {
if (!root) return null;
let leftmost = root;
while (leftmost.left) {
let head = leftmost;
while (head) {
head.left.next = head.right;
if (head.next) {
head.right.next = head.next.left;
}
head = head.next;
}
leftmost = leftmost.left;
}
return root;
};
You are given a perfect binary tree where all leaves are on the same level, and every parent has two children. Each node in this tree contains a next
pointer, which should be set to point to its immediate right neighbor at the same level. If there is no right neighbor, the next
pointer should be set to null
.
The function signature is typically: Node connect(Node root)
. You must connect all nodes' next
pointers accordingly and return the root of the tree.
At first glance, the problem looks similar to a level order traversal where you visit nodes level by level. The brute-force solution would be to use a queue to traverse each level and connect the next
pointers. However, the requirement to use constant extra space rules out such approaches.
The key insight is that since the tree is perfect, all nodes at a given level have children, and the structure is highly regular. This allows us to traverse the tree level by level using already established next
pointers, without needing extra data structures.
We can use the leftmost node of each level to start traversing that level, and then connect the children of each node as we move along the level. This way, we only use a few pointers and no additional memory.
head
) to traverse nodes horizontally using their already established next
pointers.next
to its right child.next
(i.e., it's not the last node in the level), connect its right child's next
to the left child of the node's next
neighbor.Consider the following perfect binary tree:
1 / \ 2 3 / \ / \ 4 5 6 7
next
is null
.next
to 3.next
to null
.next
to 5.next
to 6 (because 5 is the right child of 2, and 2's next
is 3, so 5's next
is 3's left child).next
to 7.next
to null
.
After running the algorithm, all next
pointers are properly set, and you can traverse each level using these pointers.
The optimized approach is both time and space efficient, meeting the problem's constraints.
By leveraging the perfect binary tree structure, we can connect all next
pointers using only constant extra space. The key is to traverse each level using already established next
pointers, connecting children as we go. This results in an elegant, efficient solution that avoids extra data structures and meets all problem constraints.