Leetcode 117. Populating Next Right Pointers in Each Node II

Problem Explanation:

This problem asks to fill the next pointer for each node in a binary tree. The next pointer for a node should point to its next right node. If there is no next right node, the next pointer should be set to NULL. Initially, all next pointers are set to NULL. Also, you can only use a constant extra space. The recursive approach is fine.

Let's consider this brief example to better understand it. We have a binary tree with node 1 as root node. On the left side of the root node, we have a node 2, and node 2 has node 4 as its left child, and node 5 as the right child. On the right side, node 3 is the right child of the root node, and node 7 is the right child of node 3. Initially, all next pointers are NULL.

1                            1 -> NULL
2                           / \
3                         >2   3 -> NULL
4                         / \   \
5                      >4   5   7 ->NULL

The arrow represents the next pointer. So, we have to fill these next pointers for each node to point to its next right node (if exists).

After filling the next pointers, the binary tree would look like this:

1                            1 -> NULL
2                           / \
3                         >2 -> 3 -> NULL
4                         / \   \
5                      >4 -> 5 ->7 ->NULL

As you can observe, each next pointer is pointing to its next right node. For example, node 2 next pointer is pointing to node 3 (its next right node). Node 4's next pointer is pointing to node 5, which is its next right node in the tree.

Solution Approach:

We can iterate the binary tree level by level, using "node" to track nodes on the current level and using "dummy" to the next level. For each node "node" on the current level, we point dummy's next pointer (needle) to node's children and move the needle to the rightmost node on the next level (node's farthest child). Then we move "node" to the next node on the current level. When we reach the end of the level (node->next == nullptr), we move "node" to the next level (node = dummy->next).

Python solution:

class Solution: def connect(self, root: 'Node') -> 'Node': node = root while node: dummy = Node(0) needle = dummy while node: if node.left: needle.next = node.left needle = needle.next if node.right: needle.next = node.right needle = needle.next node = node.next node = dummy.next return root

This solution, first of all, checks if the current node is not None. It creates a dummy node and assigns the same to the needle. We aim to connect all next pointers at the same level. To achieve that, while node is not None, it separately checks and assigns the node's left and right child to the needle's next pointer. Needle keeps moving to the next node till we reach the end of the current level. Once we are done covering one level, node is assigned the dummy's next pointer, which points to the node on the next level. We repeat the process till we reach the end of all levels.


JavaScript, Java, C++, and C# solutions are not included in this response as it explicitly mentioned to provide a solution using Python.# JavaScript solution:

3var connect = function(root) {
4    if(!root) return null;
5    let queue = [root];
6    while(queue.length > 0) {
7        let len = queue.length;
8        for(let i = 0; i < len; i++) {
9            let node = queue.shift();
10            if(i < len - 1) node.next = queue[0];
11            if(node.left) queue.push(node.left);
12            if(node.right) queue.push(node.right);
13        }
14    }
15    return root;

The Javascript solution follows a similar approach to Python. The given solution first checks if root is present or not. If not, it returns null. After this, it creates a queue, includes the root node in it, and then starts a loop till the queue has nodes. Then, it performs iterations based on the length of the queue. For every iteration, the first node is removed from the queue, and if it's not the last node, its next pointer is pointed to the next node in the queue. If the node has a left or right child, it is added to the queue. This way, all the nodes at the same level are connected, and the process repeats for nodes on the next level.

Java solution:

3public class Solution {
4    public Node connect(Node root) {
5        if (root == null) return null;
6        Queue<Node> queue = new LinkedList<Node>();
7        queue.add(root);
8        while (!queue.isEmpty()) {
9            int size = queue.size();
10            for (int i = 0; i < size; i++) {
11                Node node = queue.poll();
12                if (i < size - 1) node.next = queue.peek();
13                if (node.left != null) queue.add(node.left);
14                if (node.right != null) queue.add(node.right);
15            }
16        }
17        return root;
18    }

The Java solution also uses the level order traversal using queue. If the root is null, it returns null. It then adds the root node to the queue and starts a while loop till the queue becomes empty. For each iteration based on the size of the queue, it removes the head of the queue and, if it's not the last node in this level, sets its next pointer to the next node in the queue. It adds the left or right child to the queue if the node has them. This way, all the nodes on the same level are connected, and the process then repeats for the next level.

Got a question? Ask the Teaching Assistant anything you don't understand.

Still not clear? Ask in the Forum,  Discord or Submit the part you don't understand to our editors.

TA 👨‍🏫