LeetCode 117: Populating Next Right Pointers in Each Node II (Level Traversal with Next-Chain Builder)
LeetCode 117Binary TreePointerToday we solve LeetCode 117 - Populating Next Right Pointers in Each Node II.
Source: https://leetcode.com/problems/populating-next-right-pointers-in-each-node-ii/
English
Problem Summary
Given a binary tree (not necessarily perfect), set each node's next pointer to its right neighbor in the same level. If no neighbor exists, set it to null.
Key Insight
Use already-built next pointers to traverse the current level from left to right. While traversing, build the next level's linked chain using a dummy head + tail pointer.
Why This Beats BFS Queue
Classic BFS with queue is straightforward but needs O(w) extra space (width of tree). This pointer-chaining approach keeps extra space at O(1).
Optimal Algorithm (Step-by-Step)
1) Let levelStart = root.
2) For each level, create dummy and tail = dummy.
3) Traverse current level via curr = levelStart; curr = curr.next.
4) For each curr, append curr.left then curr.right to tail.next when non-null.
5) After finishing this level, set levelStart = dummy.next.
6) Repeat until levelStart == null.
Complexity Analysis
Time: O(n) (each node processed once).
Space: O(1) extra (excluding recursion/queue, since neither is used).
Common Pitfalls
- Forgetting to reset dummy/tail for each level.
- Traversing next level with left/right pointers directly instead of current next chain.
- Missing null checks before appending children.
Reference Implementations (Java / Go / C++ / Python / JavaScript)
/*
class Node {
public int val;
public Node left;
public Node right;
public Node next;
}
*/
class Solution {
public Node connect(Node root) {
Node levelStart = root;
while (levelStart != null) {
Node dummy = new Node(0);
Node tail = dummy;
for (Node curr = levelStart; curr != null; curr = curr.next) {
if (curr.left != null) {
tail.next = curr.left;
tail = tail.next;
}
if (curr.right != null) {
tail.next = curr.right;
tail = tail.next;
}
}
levelStart = dummy.next;
}
return root;
}
}/*
type Node struct {
Val int
Left *Node
Right *Node
Next *Node
}
*/
func connect(root *Node) *Node {
levelStart := root
for levelStart != nil {
dummy := &Node{}
tail := dummy
for curr := levelStart; curr != nil; curr = curr.Next {
if curr.Left != nil {
tail.Next = curr.Left
tail = tail.Next
}
if curr.Right != nil {
tail.Next = curr.Right
tail = tail.Next
}
}
levelStart = dummy.Next
}
return root
}/*
class Node {
public:
int val;
Node* left;
Node* right;
Node* next;
};
*/
class Solution {
public:
Node* connect(Node* root) {
Node* levelStart = root;
while (levelStart != nullptr) {
Node dummy;
dummy.next = nullptr;
Node* tail = &dummy;
for (Node* curr = levelStart; curr != nullptr; curr = curr->next) {
if (curr->left != nullptr) {
tail->next = curr->left;
tail = tail->next;
}
if (curr->right != nullptr) {
tail->next = curr->right;
tail = tail->next;
}
}
levelStart = dummy.next;
}
return root;
}
};"""
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':
level_start = root
while level_start:
dummy = Node(0)
tail = dummy
curr = level_start
while curr:
if curr.left:
tail.next = curr.left
tail = tail.next
if curr.right:
tail.next = curr.right
tail = tail.next
curr = curr.next
level_start = dummy.next
return root/**
* // Definition for a Node.
* function Node(val,left,right,next) {
* this.val = val;
* this.left = left;
* this.right = right;
* this.next = next;
* };
*/
var connect = function(root) {
let levelStart = root;
while (levelStart !== null) {
const dummy = new Node(0, null, null, null);
let tail = dummy;
for (let curr = levelStart; curr !== null; curr = curr.next) {
if (curr.left !== null) {
tail.next = curr.left;
tail = tail.next;
}
if (curr.right !== null) {
tail.next = curr.right;
tail = tail.next;
}
}
levelStart = dummy.next;
}
return root;
};中文
题目概述
给定一棵二叉树(不要求是满二叉树),请把每个节点的 next 指针指向同层右侧相邻节点;若不存在则设为 null。
核心思路
利用当前层已经建立好的 next 链从左到右扫描,同时用“哑节点 dummy + 尾指针 tail”把下一层节点串起来。
为何优于队列 BFS
常规 BFS 需要队列,额外空间是 O(w)(树宽)。这里通过层内链表遍历与构建,把额外空间降到 O(1)。
最优算法(步骤)
1)设 levelStart = root。
2)每一层开始时新建 dummy,并令 tail = dummy。
3)通过 curr = levelStart; curr = curr.next 遍历当前层。
4)遇到 curr.left / curr.right 非空就接到 tail.next,并推进 tail。
5)当前层结束后,令 levelStart = dummy.next(下一层的头)。
6)直到 levelStart == null 为止。
复杂度分析
时间复杂度:O(n)(每个节点只处理一次)。
空间复杂度:O(1)(不使用递归栈和队列)。
常见陷阱
- 每层没重置 dummy/tail。
- 遍历当前层时没有沿 next 走,导致漏节点。
- 子节点拼接时漏掉空判断。
多语言参考实现(Java / Go / C++ / Python / JavaScript)
/*
class Node {
public int val;
public Node left;
public Node right;
public Node next;
}
*/
class Solution {
public Node connect(Node root) {
Node levelStart = root;
while (levelStart != null) {
Node dummy = new Node(0);
Node tail = dummy;
for (Node curr = levelStart; curr != null; curr = curr.next) {
if (curr.left != null) {
tail.next = curr.left;
tail = tail.next;
}
if (curr.right != null) {
tail.next = curr.right;
tail = tail.next;
}
}
levelStart = dummy.next;
}
return root;
}
}/*
type Node struct {
Val int
Left *Node
Right *Node
Next *Node
}
*/
func connect(root *Node) *Node {
levelStart := root
for levelStart != nil {
dummy := &Node{}
tail := dummy
for curr := levelStart; curr != nil; curr = curr.Next {
if curr.Left != nil {
tail.Next = curr.Left
tail = tail.Next
}
if curr.Right != nil {
tail.Next = curr.Right
tail = tail.Next
}
}
levelStart = dummy.Next
}
return root
}/*
class Node {
public:
int val;
Node* left;
Node* right;
Node* next;
};
*/
class Solution {
public:
Node* connect(Node* root) {
Node* levelStart = root;
while (levelStart != nullptr) {
Node dummy;
dummy.next = nullptr;
Node* tail = &dummy;
for (Node* curr = levelStart; curr != nullptr; curr = curr->next) {
if (curr->left != nullptr) {
tail->next = curr->left;
tail = tail->next;
}
if (curr->right != nullptr) {
tail->next = curr->right;
tail = tail->next;
}
}
levelStart = dummy.next;
}
return root;
}
};"""
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':
level_start = root
while level_start:
dummy = Node(0)
tail = dummy
curr = level_start
while curr:
if curr.left:
tail.next = curr.left
tail = tail.next
if curr.right:
tail.next = curr.right
tail = tail.next
curr = curr.next
level_start = dummy.next
return root/**
* // Definition for a Node.
* function Node(val,left,right,next) {
* this.val = val;
* this.left = left;
* this.right = right;
* this.next = next;
* };
*/
var connect = function(root) {
let levelStart = root;
while (levelStart !== null) {
const dummy = new Node(0, null, null, null);
let tail = dummy;
for (let curr = levelStart; curr !== null; curr = curr.next) {
if (curr.left !== null) {
tail.next = curr.left;
tail = tail.next;
}
if (curr.right !== null) {
tail.next = curr.right;
tail = tail.next;
}
}
levelStart = dummy.next;
}
return root;
};
Comments