You're building a family tree navigation system that can quickly find any ancestor at a specific generation level. Given a tree with n nodes numbered from 0 to n-1 and a parent array where parent[i] represents the parent of node i, you need to efficiently answer queries about the kth ancestor of any node.

The kth ancestor of a node is the node that appears k steps up in the path from that node to the root. For example, if we trace the path from a node to the root, the 1st ancestor is its parent, the 2nd ancestor is its grandparent, and so on.

Your task: Implement a TreeAncestor class that can handle multiple queries efficiently:

  • TreeAncestor(int n, int[] parent) - Initialize with the tree structure
  • int getKthAncestor(int node, int k) - Return the kth ancestor of the given node, or -1 if no such ancestor exists

Since there can be up to 50,000 queries, a naive approach of traversing up the tree each time will be too slow. You'll need to use preprocessing techniques like binary lifting or dynamic programming to achieve optimal performance.

Input & Output

example_1.py โ€” Basic Tree
$ Input: n = 7, parent = [-1, 0, 0, 1, 1, 2, 2] getKthAncestor(3, 1) = ? getKthAncestor(5, 2) = ? getKthAncestor(6, 3) = ?
โ€บ Output: 1 0 -1
๐Ÿ’ก Note: Tree structure: 0 is root, 1&2 are children of 0, 3&4 are children of 1, 5&6 are children of 2. getKthAncestor(3,1) finds 1st ancestor of node 3, which is node 1. getKthAncestor(5,2) finds 2nd ancestor of node 5: 5โ†’2โ†’0. getKthAncestor(6,3) tries to find 3rd ancestor of node 6: 6โ†’2โ†’0โ†’(no parent), returns -1.
example_2.py โ€” Linear Chain
$ Input: n = 5, parent = [-1, 0, 1, 2, 3] getKthAncestor(4, 2) = ? getKthAncestor(4, 4) = ? getKthAncestor(2, 3) = ?
โ€บ Output: 2 0 -1
๐Ÿ’ก Note: Linear chain: 0โ†’1โ†’2โ†’3โ†’4. getKthAncestor(4,2) traces back 2 steps: 4โ†’3โ†’2. getKthAncestor(4,4) traces back 4 steps: 4โ†’3โ†’2โ†’1โ†’0. getKthAncestor(2,3) tries to go back 3 steps but only root's parent is null: 2โ†’1โ†’0โ†’null, returns -1.
example_3.py โ€” Edge Cases
$ Input: n = 1, parent = [-1] getKthAncestor(0, 1) = ? n = 3, parent = [-1, 0, 0] getKthAncestor(1, 0) = ?
โ€บ Output: -1 1
๐Ÿ’ก Note: Single node tree: Only root exists, asking for its parent returns -1. When k=0, we want the node itself (0th ancestor), so getKthAncestor(1,0) returns node 1.

Constraints

  • 1 โ‰ค n โ‰ค 5 ร— 104
  • parent[0] == -1 indicating that 0 is the root
  • 0 โ‰ค parent[i] < n for all 0 < i < n
  • 0 โ‰ค node < n
  • 1 โ‰ค k โ‰ค n
  • At most 5 ร— 104 queries will be made

Visualization

Tap to expand
Binary Lifting Tree012345Binary Lifting TableNode2โฐ(1)2ยน(2)2ยฒ(4)2ยณ(8)5420-1420-1-1310-1-1Query: getKthAncestor(5, 5)5 in binary: 101โ‚‚ = 4 + 1Step 1: Jump 2โฐ=1 โ†’ 5 to 4Step 2: Jump 2ยฒ=4 โ†’ 4 to 0Result: 0 โœ“
Understanding the Visualization
1
Build Elevator System
Pre-compute where each 'elevator' (power-of-2 jump) takes you from every node
2
Convert Distance to Binary
For k=13, convert to binary: 1101โ‚‚ = 8+4+1
3
Make Combined Jumps
Take elevator of size 1, then 4, then 8 to reach 13 floors up
4
Arrive at Destination
Reach the kth ancestor in O(log k) time instead of O(k)
Key Takeaway
๐ŸŽฏ Key Insight: Binary lifting transforms O(k) linear traversal into O(log k) by pre-computing power-of-2 jumps and using binary decomposition
Asked in
Google 35 Meta 28 Amazon 22 Microsoft 15
38.2K Views
Medium-High Frequency
~35 min Avg. Time
1.5K Likes
Ln 1, Col 1
Smart Actions
๐Ÿ’ก Explanation
AI Ready
๐Ÿ’ก Suggestion Tab to accept Esc to dismiss
// Output will appear here after running code
Code Editor Closed
Click the red button to reopen