Last Updated: 6 Nov, 2020

Kth ancestor of a node in binary tree

Hard
Asked in companies
AmazonFlipkartWalmart

Problem statement

You are given an arbitrary binary tree consisting of N nodes numbered from 1 to N, an integer 'K', and a node 'TARGET_NODE_VAL' from the tree. You need to find the Kth ancestor of the node 'TARGET_NODE_VAL'. If there is no such ancestor, then print -1.

The Kth ancestor of a node in a binary tree is the Kth node in the path going up from the given node to the root of the tree. Refer to sample test cases for further explanation.

Note:
1. The given node 'TARGET_NODE_VAL' is always present in the tree.
2. The value of each node in the tree is unique.
3. Notice that the Kth ancestor node if present will always be unique.
Input Format:
The first line contains a single integer T representing the number of test cases. 

The first line of each test case will contain the values of the nodes of the tree in the level order form ( -1 for NULL node) Refer to the example for further clarification.

The second line of each test case will contain two space-separated integers K and TARGET_NODE_VAL which are the value of the Kth ancestor to be found of the node and the value of the node given for which the Kth ancestor is to be computed respectively.

Example: 
Consider the binary tree:

altImage

The input of the tree depicted in the image above will be like: 
 1
 2 3
 4 -1 5 6
-1 7 -1 -1 -1 -1
-1 -1

Explanation :
Level 1 :
The root node of the tree is 1

Level 2 :
Left child of 1 = 2
Right child of 1 = 3

Level 3 :
Left child of 2 = 4
Right child of 2 = null (-1)
Left child of 3 = 5
Right child of 3 = 6

Level 4 :
Left child of 4 = null (-1)
Right child of 4 = 7
Left child of 5 = null (-1)
Right child of 5 = null (-1)
Left child of 6 = null (-1)
Right child of 6 = null (-1)

Level 5 :
Left child of 7 = null (-1)
Right child of 7 = null (-1)

The first not-null node (of the previous level) is treated as the parent of the first two nodes of the current level. The second not-null node (of the previous level) is treated as the parent node for the next two nodes of the current level and so on.

The input ends when all nodes at the last level are null (-1).
Output Format:
For each test case, print the value of the Kth ancestor of the node in a separate line. If it doesn’t exist, then print -1.
Note:
You do not need to print anything, it has already been taken care of. Just implement the given function. 
Constraints:
1 <= T <= 100
1 <= N <= 3000
1 <= K <= 10^9
1 <= NODE_VAL <= 10^9

Time Limit: 1 sec

Approaches

01 Approach

  • What the trivial solution suggests is that we store the parents of all the nodes till we get our target node. To do this, we can simply run a breadth-first search on the tree and traverse the tree level by level, storing the current node as the parent of its left and right child.
  • Traverse the tree level order wise using a queue and keep on storing the parents of the nodes in a hashmap or any suitable data structure.
  • For doing this, let us suppose that the front element of the queue is X, which is just popped from the queue,  now if X has a left child, then PAR[X→LEFT] = X. Similarly, if X has a right child then PAR[X→RIGHT] = X, where PAR[NODE] is the immediate parent of ‘NODE’.
  • The 1st ancestor of node N is PAR[N]. 2nd ancestor is PAR[PAR[N]] and so on. To get the Kth parent, we can do this thing K times and keep on decrementing the value of K.
  • When K becomes 0, return the parent, and if the value is -1 of the parent (i.e. we have reached the root of the tree) then return -1

02 Approach

  • Instead of creating another array explicitly for storing the parents of the nodes, we can achieve the same task using a depth-first search on the given tree. As we are concerned with only the given node and its ancestors, so we don’t actually need to store parents of the nodes which are not in the path from the root node to the given node and that is where we can reduce the space complexity.
  • The main idea is to traverse the tree using a depth-first search and find the given node and then backtrack exactly K times to reach the Kth ancestor. As we know, the DFS goes recursively from parent to its child and then to grandchild and so on, thus as soon as we hit the given node, the recursion stack has all the ancestors of this node.
  • Let’s say we have a function FIND_KTH_ANCESTOR() which will return the Kth ancestor recursively.
  • Recursively search for the given node in the left or the right subtree. When we hit the node, return this node to the calling function and keep on decrementing K. If we reach the root and K is still not zero, then return -1, else when K becomes 0, the current node is our answer.