Path In Zigzag Labelled Binary Tree
MedPrompt
In an infinite binary tree where every node has two children, the nodes are labelled in row order.
In the odd numbered rows (ie., the first, third, fifth,...), the labelling is left to right, while in the even numbered rows (second, fourth, sixth,...), the labelling is right to left.

Given the label of a node in this tree, return the labels in the path from the root of the tree to the node with that label.
Example 1:
Input: label = 14
Output: [1,3,4,14]Example 2:
Input: label = 26
Output: [1,2,6,10,26]
Constraints:
1 <= label <= 10^6
Approaches
2 approaches with complexity analysis and trade-offs.
This approach involves a direct simulation of the tree's construction. We build the tree level by level up to the level containing the target label. While building, we maintain a map of each node's label to its parent's label. After the necessary portion of the tree is constructed and the parent relationships are mapped, we can easily backtrack from the target label to the root to find the required path.
Algorithm
- Determine the level of the target
label. Let this bemax_level. - Create a map to store parent-child relationships, for instance,
Map<Integer, Integer> parentMap. - Simulate the tree construction level by level from the root (level 0) up to
max_level. - For each level, calculate the range of labels and generate them according to the zigzag pattern (left-to-right for odd rows, right-to-left for even rows).
- As each level's nodes are generated, populate the
parentMapby linking them to their parents from the previous level. - Once the map is built, trace the path from the target
labelback to the root by repeatedly querying theparentMap. - Collect the labels in a list and reverse it to obtain the final path from root to target.
Walkthrough
The algorithm proceeds as follows:
- First, we determine the depth of the tree required to include the given
label. The leveldof a node with a givenlabelcan be found byd = floor(log2(label)). - We then construct the tree level by level. We use a list to hold the labels of the nodes at the current level and a map to store
child -> parentmappings. - We start with level 0, which contains only the root node with label 1.
- We then iterate from level 1 up to the target level. In each iteration, we generate the labels for the new level. The labels are generated from left-to-right (
2^dto2^(d+1)-1) if the row number is odd (i.e., leveldis even), and right-to-left if the row number is even (i.e., leveldis odd). - For each parent in the previous level, we associate its two children from the newly generated list of labels and update our parent map.
- After the simulation is complete, the
parentMapcontains all the necessary links to trace the path. We start from the targetlabel, add it to our result path, and then find its parent from the map. We repeat this process until we reach the root (label 1). - Finally, the collected path is reversed to get the correct order from root to the target node.
import java.util.*; class Solution { public List<Integer> pathInZigZagTree(int label) { if (label == 1) { return Collections.singletonList(1); } Map<Integer, Integer> parentMap = new HashMap<>(); parentMap.put(1, 0); // Using 0 as a sentinel for no parent Queue<Integer> queue = new LinkedList<>(); queue.add(1); int level = 0; boolean found = false; while (!queue.isEmpty() && !found) { int levelSize = queue.size(); level++; int start = 1 << level; int end = (1 << (level + 1)) - 1; List<Integer> children = new ArrayList<>(); if (level % 2 == 1) { // Even row number, R-L labeling for (int i = end; i >= start; i--) { children.add(i); } } else { // Odd row number, L-R labeling for (int i = start; i <= end; i++) { children.add(i); } } for (int i = 0; i < levelSize; i++) { int parent = queue.poll(); int child1 = children.get(2 * i); int child2 = children.get(2 * i + 1); parentMap.put(child1, parent); parentMap.put(child2, parent); queue.add(child1); queue.add(child2); if (child1 == label || child2 == label) { found = true; } } } LinkedList<Integer> path = new LinkedList<>(); int current = label; while (current != 0) { path.addFirst(current); current = parentMap.get(current); } return path; }}Complexity
Time
O(label) - To find the path for a given `label`, we must construct the tree up to the level of that label. The number of nodes in the tree grows exponentially with the level. The total number of nodes processed is proportional to the value of `label` itself.
Space
O(label) - The space required is dominated by the `parentMap` and the queue used for level-order traversal. In the worst case, we might store information for all nodes up to the level of the target `label`. The number of nodes up to level `d` is `2^(d+1) - 1`. Since `d` is `log2(label)`, the number of nodes is approximately `2*label`.
Trade-offs
Pros
Straightforward to implement as it directly follows the problem's description.
Easy to reason about and debug.
Cons
Highly inefficient for large labels as both time and space complexity are linear with respect to the label value.
Can lead to
OutOfMemoryErrorfor labels close to the constraint10^6.
Solutions
Solution
class Solution {public List<Integer> pathInZigZagTree(int label) { int x = 1, i = 1; while ((x << 1) <= label) { x <<= 1; ++i; } List<Integer> ans = new ArrayList<>(); for (; i > 0; --i) { ans.add(label); label = ((1 << (i - 1)) + (1 << i) - 1 - label) >> 1; } Collections.reverse(ans); return ans; }}Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.