Shortest path between two nodes in array like representation of binary tree

Consider a binary tree in which each node has two children except the leaf nodes. If a node is labeled as ‘v’ then its right children will be labeled as 2v+1 and left children as 2v. Root is labelled as

Given two nodes labeled as i and j, the task is to find the shortest distance and the path from i to j. And print the path of node i and node j from root node.

Examples:

Input  : i = 1, j = 2        
Output : 1
         Path is 1 2

Input  : i = 4, j = 3
Output : 3
         Path is 4 2 1 3

This problem is mainly an extension of Find distance between two given keys of a Binary Tree. Here we not only find shortest distance, but also the path.

The between the two nodes i and j will be equal to dist(i, LCA(i, j)) + dist(j, LCA(i, j)) where LCA means lowest common ancestor of nodes labeled as i and j. If a number x is represented in binary form then 2*x can be represented by appending 0 to the binary representation of x and 2x+1 can be represented by appending 1 to the binary representation of x. This is because when we append 0 all the terms present in binary form of x shift left, so it gets doubled similarly when we append 1, we get 2x+1. Suppose the binary representation of a node is 1010 this tells us the path of this node from root. First term ‘1’ represents root second term 0 represents left turn then third term 1 represents right turn from previous node and finally 0 represents left turn.

Shortest-Path-Diagram

Node 10 in binary form is 1010 and 13 in binary form is 1101 secondly length of binary representation of any node also tells about its level in binary tree. Suppose binary representation of i is m length and is i_1 i_2i_m and binary representation of node j is n length j_1 j_2……j_n.
Thus we know the path of i and j from root .Find out k such that for all p<=k i_p = j_p.This is the LCA of i and j in binary form .So dist(i, LCA(i, j)) will be m – k and dist(j, LCA(i, j)) = n – k. so answer will be m + n – 2k. And printing the path is also not a big issue just store the path of i to LCA and path of j to LCA and concatenate them.

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ representation of finding shortest
// distance between node i and j
#include <bits/stdc++.h>
using namespace std;
  
// prints the path between node i and node j
void ShortestPath(int i, int j, int k, int m,
                                       int n)
{
    // path1 stores path of node i to lca and
    // path2 stores path of node j to lca
    vector<int> path1, path2;
    int x = m - 1;
  
    // push node i in path1
    path1.push_back(i);
  
    // keep pushing parent of node labelled
    // as i to path1 until lca is reached
    while (x != k) {
        path1.push_back(i / 2);
        i = i / 2;
        x--;
    }
    int y = n - 1;
  
    // push node j to path2
    path2.push_back(j);
  
    // keep pushing parent of node j till
    // lca is reached
    while (y != k) {
        path2.push_back(j / 2);
        j = j / 2;
        y--;
    }
  
    // printing path from node i to lca
    for (int l = 0; l < path1.size(); l++)
        cout << path1[l] << " ";
  
    // printing path from lca to node j
    for (int l = path2.size() - 2; l >= 0; l--)
        cout << path2[l] << " ";
    cout << endl;
}
  
// returns the shortest distance between
// nodes labelled as i and j
int ShortestDistance(int i, int j)
{
    // vector to store binary form of i and j
    vector<int> v1, v2;
  
    // finding binary form of i and j
    int p1 = i;
    int p2 = j;
    while (i != 0) {
        v1.push_back(i % 2);
        i = i / 2;
    }
    while (j != 0) {
        v2.push_back(j % 2);
        j = j / 2;
    }
  
    // as binary form will be in reverse order
    // reverse the vectors
    reverse(v1.begin(), v1.end());
    reverse(v2.begin(), v2.end());
  
    // finding the k that is lca (i, j)
    int m = v1.size(), n = v2.size(), k = 0;
    if (m < n) {
        while (k < m && v1[k] == v2[k])
            k++;
    } else {
        while (k < n && v1[k] == v2[k])
            k++;
    }
  
    ShortestPath(p1, p2, k - 1, m, n);
    return m + n - 2 * k;
}
  
// Driver function
int main()
{
    cout << ShortestDistance(1, 2) << endl;
    cout << ShortestDistance(4, 3) << endl;
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java representation of finding shortest 
// distance between node i and j 
import java.util.*;
  
class GFG
{
      
// prints the path between node i and node j 
static void ShortestPath(int i, int j, int k, int m, 
                                    int n) 
    // path1 stores path of node i to lca and 
    // path2 stores path of node j to lca 
    Vector<Integer> path1=new Vector<Integer>(), 
                    path2=new Vector<Integer>(); 
    int x = m - 1
  
    // push node i in path1 
    path1.add(i); 
  
    // keep pushing parent of node labelled 
    // as i to path1 until lca is reached 
    while (x != k) 
    
        path1.add(i / 2); 
        i = i / 2
        x--; 
    
    int y = n - 1
  
    // push node j to path2 
    path2.add(j); 
  
    // keep pushing parent of node j till 
    // lca is reached 
    while (y != k) 
    
        path2.add(j / 2); 
        j = j / 2
        y--; 
    
  
    // printing path from node i to lca 
    for (int l = 0; l < path1.size(); l++) 
        System.out.print( path1.get(l) + " "); 
  
    // printing path from lca to node j 
    for (int l = path2.size() - 2; l >= 0; l--) 
        System.out.print( path2.get(l) + " "); 
    System.out.println();
  
// returns the shortest distance between 
// nodes labelled as i and j 
static int ShortestDistance(int i, int j) 
    // vector to store binary form of i and j 
    Vector<Integer> v1=new Vector<Integer>(), 
                    v2=new Vector<Integer>(); 
  
    // finding binary form of i and j 
    int p1 = i; 
    int p2 = j; 
    while (i != 0)
    
        v1.add(i % 2); 
        i = i / 2
    
    while (j != 0)
    
        v2.add(j % 2); 
        j = j / 2
    
  
    // as binary form will be in reverse order 
    // reverse the vectors 
    Collections.reverse(v1); 
    Collections.reverse(v2); 
  
    // finding the k that is lca (i, j) 
    int m = v1.size(), n = v2.size(), k = 0
    if (m < n) 
    
        while (k < m && v1.get(k) == v2.get(k)) 
            k++; 
    
    else 
    
        while (k < n && v1.get(k) == v2.get(k)) 
            k++; 
    
  
    ShortestPath(p1, p2, k - 1, m, n); 
    return m + n - 2 * k; 
  
// Driver code 
public static void main(String args[])
    System.out.println( ShortestDistance(1, 2) ); 
    System.out.println(ShortestDistance(4, 3) ); 
}
}
  
// This code is contributed by Arnab Kundu

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 representation of finding 
# shortest distance between node i and j 
  
# Prints the path between node i and node j 
def ShortestPath(i, j, k, m, n): 
  
    # path1 stores path of node i to lca and 
    # path2 stores path of node j to lca 
    path1, path2 = [], [] 
    x = m - 1
  
    # push node i in path1 
    path1.append(i) 
  
    # keep pushing parent of node labelled 
    # as i to path1 until lca is reached 
    while x != k: 
        path1.append(i // 2
        i = i // 2
        x -= 1
      
    y = n - 1
  
    # push node j to path2 
    path2.append(j) 
  
    # keep pushing parent of node 
    # j till lca is reached 
    while y != k: 
        path2.append(j / 2
        j = j // 2
        y -= 1
      
    # printing path from node i to lca 
    for l in range(0, len(path1)): 
        print(path1[l], end = " "
  
    # printing path from lca to node j 
    for l in range(len(path2) - 2, -1, -1): 
        print(path2[l], end = " "
    print() 
  
# Returns the shortest distance 
# between nodes labelled as i and j 
def ShortestDistance(i, j): 
  
    # vector to store binary form of i and j 
    v1, v2 = [], [] 
  
    # finding binary form of i and j 
    p1, p2 = i, j 
    while i != 0
        v1.append(i % 2
        i = i // 2
      
    while j != 0
        v2.append(j % 2
        j = j // 2
      
    # as binary form will be in reverse 
    # order reverse the vectors 
    v1 = v1[::-1
    v2 = v2[::-1
  
    # finding the k that is lca (i, j) 
    m, n, k = len(v1), len(v2), 0
    if m < n:
        while k < m and v1[k] == v2[k]: 
            k += 1
      
    else:
        while k < n and v1[k] == v2[k]: 
            k += 1
      
    ShortestPath(p1, p2, k - 1, m, n) 
    return m + n - 2 *
  
# Driver Code
if __name__ == "__main__"
  
    print(ShortestDistance(1, 2)) 
    print(ShortestDistance(4, 3)) 
  
# This code is contributed by Rituraj Jain

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C#  representation of finding shortest 
// distance between node i and j 
using System;
using System.Collections.Generic;    
      
class GFG
{
       
// prints the path between node i and node j 
static void ShortestPath(int i, int j, int k, int m, 
                                    int n) 
    // path1 stores path of node i to lca and 
    // path2 stores path of node j to lca 
    List<int> path1=new List<int>(), 
                    path2=new List<int>(); 
    int x = m - 1; 
   
    // push node i in path1 
    path1.Add(i); 
   
    // keep pushing parent of node labelled 
    // as i to path1 until lca is reached 
    while (x != k) 
    
        path1.Add(i / 2); 
        i = i / 2; 
        x--; 
    
    int y = n - 1; 
   
    // push node j to path2 
    path2.Add(j); 
   
    // keep pushing parent of node j till 
    // lca is reached 
    while (y != k) 
    
        path2.Add(j / 2); 
        j = j / 2; 
        y--; 
    
   
    // printing path from node i to lca 
    for (int l = 0; l < path1.Count; l++) 
        Console.Write( path1[l] + " "); 
   
    // printing path from lca to node j 
    for (int l = path2.Count - 2; l >= 0; l--) 
        Console.Write( path2[l] + " "); 
    Console.WriteLine();
   
// returns the shortest distance between 
// nodes labelled as i and j 
static int ShortestDistance(int i, int j) 
    // vector to store binary form of i and j 
    List<int> v1=new List<int>(), 
                    v2=new List<int>(); 
   
    // finding binary form of i and j 
    int p1 = i; 
    int p2 = j; 
    while (i != 0)
    
        v1.Add(i % 2); 
        i = i / 2; 
    
    while (j != 0)
    
        v2.Add(j % 2); 
        j = j / 2; 
    
   
    // as binary form will be in reverse order 
    // reverse the vectors 
    v1.Reverse(); 
    v2.Reverse(); 
   
    // finding the k that is lca (i, j) 
    int m =v1.Count, n =v2.Count, k = 0; 
    if (m < n) 
    
        while (k < m && v1[k] == v2[k]) 
            k++; 
    
    else
    
        while (k < n && v1[k] == v2[k]) 
            k++; 
    
   
    ShortestPath(p1, p2, k - 1, m, n); 
    return m + n - 2 * k; 
   
// Driver code 
public static void Main(String []args)
    Console.WriteLine( ShortestDistance(1, 2) ); 
    Console.WriteLine(ShortestDistance(4, 3) ); 
}
}
  
// This code is contributed by Princi Singh

chevron_right


Output:

1 2
1
4 2 1 3
3

Time Complexity O(log_2i + log_2j)

This article is contributed by Ayush Jha. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.



My Personal Notes arrow_drop_up



Article Tags :
Practice Tags :


Be the First to upvote.


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.