Skip to content
Related Articles
Open in App
Not now

Related Articles

Step by step Shortest Path from source node to destination node in a Binary Tree

Improve Article
Save Article
  • Difficulty Level : Medium
  • Last Updated : 31 Jan, 2023
Improve Article
Save Article

Given a root of binary tree and two integers startValue and destValue denoting the starting and ending node respectively. The task is to find the shortest path from the start node to the end node and print the path in the form of directions given below. 

  1. Going from one node to its left child node is indicated by the letter ‘L’.
  2. Going from one node to its right child node is indicated by the letter ‘R’.
  3. To navigate from a node to its parent node, use the letter ‘U’.

Examples: 

Input: root = [5, 1, 2, 3, null, 6, 4], startValue = 3, destValue = 6

              5
          /      \
       1          2
    /          /     \
  3        6         4

Output: “UURL” 
Explanation: The shortest path is: 3 → 1 → 5 → 2 → 6.

Input: root = [2, 1], startValue = 2, destValue = 1

            2
          /
       1

Output: “L”
Explanation: The shortest path is: 2 → 1.

 

Approach: The simplest way to solve this problem is to use the LCA (Lowest Common Ancestor) of a binary tree. Follow the steps below to solve the given problem. 

  • Apply LCA to get a new root.
  • Get the Path from the new root to start and dest.
  • Concatenate startPath and destPath, and make sure to replace startPath’s char with ‘U’.

Below is the implementation of the above approach. 

C++




// C++ program for above approach
#include <iostream>
using namespace std;
 
// Structure of Tree
class TreeNode {
public:
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int val2)
    {
        val = val2;
        left = NULL;
        right = NULL;
    }
};
 
// Function to find LCA of two nodes
TreeNode* lca(TreeNode* root,
              int startValue,
              int destValue)
{
 
    // Base Case
    if (!root)
        return NULL;
 
    if (root->val == startValue)
        return root;
    if (root->val == destValue)
        return root;
    auto l = lca(root->left,
                 startValue, destValue);
    auto r = lca(root->right,
                 startValue, destValue);
 
    if (l && r)
        return root;
 
    return l ? l : r;
}
bool getPath(TreeNode* root,
             int value,
             string& path)
{
 
    // Base Cases
    if (!root)
        return false;
    if (root->val == value)
        return true;
 
    path += 'L';
    auto res = getPath(root->left,
                       value, path);
    if (res)
        return true;
    path.pop_back();
    path += 'R';
    res = getPath(root->right,
                  value, path);
    if (res)
        return true;
    path.pop_back();
    return false;
}
 
// Function to get directions
string getDirections(TreeNode* root,
                     int startValue,
                     int destValue)
{
    // Find the LCA first
    root = lca(root, startValue, destValue);
 
    string p1, p2;
 
    // Get the path
    getPath(root, startValue, p1);
    getPath(root, destValue, p2);
    for (auto& c : p1)
        c = 'U';
 
    // Return the concatenation
    return p1 + p2;
}
 
// Driver Code
int main()
{
 
    /*
             5
           /    \
         1       2
        /       /  \
      3        6    4
 
   */
    TreeNode* root = new TreeNode(5);
    root->left = new TreeNode(1);
    root->right = new TreeNode(2);
    root->left->left = new TreeNode(3);
    root->right->left = new TreeNode(6);
    root->right->right = new TreeNode(4);
 
    int startValue = 3;
    int endValue = 6;
 
    // Function Call
    string ans = getDirections(
      root, startValue, endValue);
 
    // Print answer
    cout << ans;
}


Python3




# Python program for above approach
 
# Structure of Tree
class TreeNode :
    def __init__(self, val2):
        self.val = val2;
        self.left = None;
        self.right = None;
 
# Function to find LCA of two nodes
def lca(root, startValue, destValue):
     
    # Base Case
    if (not root):
        return None;
 
    if (root.val == startValue):
        return root;
    if (root.val == destValue):
        return root;
    l = lca(root.left,
        startValue, destValue);
    r = lca(root.right,
        startValue, destValue);
 
    if (l and r):
        return root;
 
    return l if l else r;
 
def getPath(root, value, path) :
     
    # Base Cases
    if (not root):
        return False;
    if (root.val == value):
        return True;
 
    path.append('L');
    res = getPath(root.left, value, path);
    if (res):
        return True;
         
    path.pop();
    path.append('R');
    res = getPath(root.right, value, path);
                   
    if (res):
        return True;
         
    path.pop();
    return False;
 
 
# Function to get directions
def getDirections(root, startValue, destValue) :
     
    # Find the LCA first
    root = lca(root, startValue, destValue);
 
    p1 = []
    p2 = []
 
    # Get the path
    getPath(root, startValue, p1);
    getPath(root, destValue, p2);
    for i in range(len(p1)):
        p1[i] = 'U';
 
    # Return the concatenation
    s = ""
    for i in range(len(p1)):
        s += p1[i];
    for i in range(len(p2)):
        s += p2[i];
    return s;
 
# Driver Code
"""
         5
       /    \
     1       2
    /       /  \
  3        6    4
"""
 
root = TreeNode(5);
root.left = TreeNode(1);
root.right = TreeNode(2);
root.left.left = TreeNode(3);
root.right.left = TreeNode(6);
root.right.right = TreeNode(4);
 
startValue = 3;
endValue = 6;
 
# Function Call
ans = getDirections(root, startValue,
                        endValue);
 
# Print answer
print(ans)
 
# self code is contributed by Saurabh Jaiswal


Javascript




<script>
 
// JavaScript program for above approach
 
// Structure of Tree
class TreeNode
{
    constructor(val2)
    {
        this.val = val2;
        this.left = null;
        this.right = null;
    }
};
 
// Function to find LCA of two nodes
function lca(root, startValue, destValue)
{
     
    // Base Case
    if (!root)
        return null;
 
    if (root.val == startValue)
        return root;
    if (root.val == destValue)
        return root;
    let l = lca(root.left,
        startValue, destValue);
    let r = lca(root.right,
        startValue, destValue);
 
    if (l && r)
        return root;
 
    return l ? l : r;
}
 
function getPath(root, value, path)
{
     
    // Base Cases
    if (!root)
        return false;
    if (root.val == value)
        return true;
 
    path.push('L');
    let res = getPath(root.left,
                      value, path);
    if (res)
        return true;
         
    path.pop();
    path.push('R');
    res = getPath(root.right,
                  value, path);
                   
    if (res)
        return true;
         
    path.pop();
    return false;
}
 
// Function to get directions
function getDirections(root, startValue,
                       destValue)
{
     
    // Find the LCA first
    root = lca(root, startValue, destValue);
 
    let p1 = [], p2 = [];
 
    // Get the path
    getPath(root, startValue, p1);
    getPath(root, destValue, p2);
    for(let i = 0; i < p1.length; i++)
        p1[i] = 'U';
 
    // Return the concatenation
    let s = ""
    for(let i = 0; i < p1.length; i++)
    {
        s += p1[i];
    }
    for(let i = 0; i < p2.length; i++)
    {
        s += p2[i];
    }
    return s;
}
 
// Driver Code
/*
         5
       /    \
     1       2
    /       /  \
  3        6    4
 
*/
let root = new TreeNode(5);
root.left = new TreeNode(1);
root.right = new TreeNode(2);
root.left.left = new TreeNode(3);
root.right.left = new TreeNode(6);
root.right.right = new TreeNode(4);
 
let startValue = 3;
let endValue = 6;
 
// Function Call
let ans = getDirections(root, startValue,
                        endValue);
 
// Print answer
document.write(ans)
 
// This code is contributed by Potta Lokesh
 
</script>


Output

UURL

Time complexity: O(3N), Because three traversals are done.
Auxiliary Space: O(1)

Efficient Approach: This approach is implementation based but LCA is not used in this approach. Follow the steps below to solve the given problem.  

  • Build directions for both start and destination from the root.
  • Say we get “LLRRL” and “LRR”.
  • Remove common prefix path.
  • We remove “L”, and now start direction is “LRRL”, and destination – “RR”
  • Replace all steps in the start direction to “U” and add the destination direction.
  • The result is “UUUU” + “RR”.

Below is the implementation of the above approach.  

C++




// C++ program for above approach
#include <bits/stdc++.h>
using namespace std;
 
// Structure of Tree
class TreeNode {
public:
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int val2)
    {
        val = val2;
        left = NULL;
        right = NULL;
    }
};
 
// Find Function
bool find(TreeNode* n, int val,
          string& path)
{
    if (n->val == val)
        return true;
    if (n->left && find(n->left,
                        val, path)) {
        path.push_back('L');
        return true;
    }
    if (n->right && find(n->right,
                         val, path)) {
        path.push_back('R');
        return true;
    }
    return false;
}
 
// Function to keep track
// of directions at any point
string getDirections(TreeNode* root,
                     int startValue,
                     int destValue)
{
 
    // To store the startPath and destPath
    string s_p, d_p;
    find(root, startValue, s_p);
    find(root, destValue, d_p);
 
    while (!s_p.empty() && !d_p.empty()
           && s_p.back() == d_p.back()) {
        s_p.pop_back();
        d_p.pop_back();
    }
 
    for (int i = 0; i < s_p.size(); i++) {
        s_p[i] = 'U';
    }
    reverse(d_p.begin(), d_p.end());
    string ans = s_p + d_p;
    return ans;
}
 
// Driver Code
int main()
{
 
    /*
             5
           /    \
         1       2
        /       /  \
      3        6    4
 
 
   */
 
    TreeNode* root = new TreeNode(5);
    root->left = new TreeNode(1);
    root->right = new TreeNode(2);
    root->left->left = new TreeNode(3);
    root->right->left = new TreeNode(6);
    root->right->right = new TreeNode(4);
 
    int startValue = 3;
    int endValue = 6;
 
    // Function Call
    string ans = getDirections(
      root, startValue, endValue);
 
    // Print the result
    cout << ans;
}


Python




# Python program for above approach
class TreeNode:
    def __init__(self, val2):
        self.val = val2
        self.left = None
        self.right = None
 
# Find Function
def find(n, val, path):
    if n.val == val:
        return True
    if n.left and find(n.left, val, path):
        path.append('L')
        return True
    if n.right and find(n.right, val, path):
        path.append('R')
        return True
    return False
 
# Function to keep track
# of directions at any point
def getDirections(root, startValue, destValue):
   
  # To store the startPath and destPath
    s_p, d_p = [], []
    find(root, startValue, s_p)
    find(root, destValue, d_p)
 
    while s_p and d_p and s_p[-1] == d_p[-1]:
        s_p.pop()
        d_p.pop()
 
    for i in range(len(s_p)):
        s_p[i] = 'U'
    d_p.reverse()
    ans = s_p + d_p
    return ans
 
 
if __name__ == '__main__':
    root = TreeNode(5)
    root.left = TreeNode(1)
    root.right = TreeNode(2)
    root.left.left = TreeNode(3)
    root.right.left = TreeNode(6)
    root.right.right = TreeNode(4)
 
    startValue = 3
    endValue = 6
 
    ans = getDirections(root, startValue, endValue)
    print(ans)
 
    # This code is contributed by aadityamaharshi21.


Output

UURL

Time complexity: O(N)
Auxiliary Space: O(1), If recursion stack space if neglected. 

 


My Personal Notes arrow_drop_up
Related Articles

Start Your Coding Journey Now!