Step by step Shortest Path from source node to destination node in a Binary Tree
Last Updated :
27 Mar, 2023
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.
- Going from one node to its left child node is indicated by the letter 'L'.
- Going from one node to its right child node is indicated by the letter 'R'.
- 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;
}
Java
// Java program for above approach
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x)
{
val = x;
left = null;
right = null;
}
}
// Function to find LCA of two nodes
class Solution {
TreeNode lca(TreeNode root, int startValue,
int destValue)
{
// Base Case
if (root == null) {
return null;
}
if (root.val == startValue) {
return root;
}
if (root.val == destValue) {
return root;
}
TreeNode l = lca(root.left, startValue, destValue);
TreeNode r = lca(root.right, startValue, destValue);
if (l != null && r != null) {
return root;
}
return l != null ? l : r;
}
boolean getPath(TreeNode root, int value,
StringBuilder path)
{
// Base Cases
if (root == null) {
return false;
}
if (root.val == value) {
return true;
}
path.append("L");
boolean res = getPath(root.left, value, path);
if (res) {
return true;
}
path.deleteCharAt(path.length() - 1);
path.append("R");
res = getPath(root.right, value, path);
if (res) {
return true;
}
path.deleteCharAt(path.length() - 1);
return false;
}
// Function to get directions
String getDirections(TreeNode root, int startValue,
int destValue)
{
// Find the LCA first
root = lca(root, startValue, destValue);
StringBuilder p1 = new StringBuilder();
StringBuilder p2 = new StringBuilder();
// Get the path
getPath(root, startValue, p1);
getPath(root, destValue, p2);
for (int i = 0; i < p1.length(); i++) {
p1.setCharAt(i, 'U');
}
// Return the concatenation
return p1.append(p2).toString();
}
}
// Driver Code
public class Main {
public static void main(String[] args)
{
/*
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
Solution solution = new Solution();
String ans = solution.getDirections(
root, startValue, endValue);
// Print answer
System.out.println(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
C#
using System;
using System.Text;
class TreeNode
{
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int x)
{
val = x;
left = null;
right = null;
}
}
class Solution
{
public TreeNode lca(TreeNode root, int startValue, int destValue)
{
// Base Case
if (root == null)
{
return null;
}
if (root.val == startValue)
{
return root;
}
if (root.val == destValue)
{
return root;
}
TreeNode l = lca(root.left, startValue, destValue);
TreeNode r = lca(root.right, startValue, destValue);
if (l != null && r != null)
{
return root;
}
return l != null ? l : r;
}
public bool getPath(TreeNode root, int value, StringBuilder path)
{
// Base Cases
if (root == null)
{
return false;
}
if (root.val == value)
{
return true;
}
path.Append("L");
bool res = getPath(root.left, value, path);
if (res)
{
return true;
}
path.Remove(path.Length - 1, 1);
path.Append("R");
res = getPath(root.right, value, path);
if (res)
{
return true;
}
path.Remove(path.Length - 1, 1);
return false;
}
public string getDirections(TreeNode root, int startValue, int destValue)
{
// Find the LCA first
root = lca(root, startValue, destValue);
StringBuilder p1 = new StringBuilder();
StringBuilder p2 = new StringBuilder();
// Get the path
getPath(root, startValue, p1);
getPath(root, destValue, p2);
for (int i = 0; i < p1.Length; i++)
{
p1[i] = 'U';
}
// Return the concatenation
return p1.Append(p2).ToString();
}
}
public class Program
{
public static void Main(string[] args)
{
/*
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
Solution solution = new Solution();
string ans = solution.getDirections(root, startValue, endValue);
// Print answer
Console.WriteLine(ans);
}
}
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>
Time complexity: O(3N), Because three traversals are done.
Auxiliary Space: O(N)
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;
}
Java
// Java Code
import java.util.ArrayList;
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int val2)
{
this.val = val2;
this.left = null;
this.right = null;
}
}
class solution {
// Find Function
public static boolean find(TreeNode n, int val,
ArrayList<String> path)
{
if (n.val == val) {
return true;
}
if (n.left != null && find(n.left, val, path)) {
path.add("R");
return true;
}
if (n.right != null && find(n.right, val, path)) {
path.add("L");
return true;
}
return false;
}
// Function to keep track of directions at any point
public static ArrayList<String>
getDirections(TreeNode root, int startValue,
int destValue)
{
// To store the startPath and destPath
ArrayList<String> s_p = new ArrayList<>();
ArrayList<String> d_p = new ArrayList<>();
find(root, startValue, s_p);
find(root, destValue, d_p);
while (s_p.size() > 0 && d_p.size() > 0
&& s_p.get(s_p.size() - 1)
.equals(d_p.get(d_p.size() - 1))) {
s_p.remove(s_p.size() - 1);
d_p.remove(d_p.size() - 1);
}
for (int i = 0; i < s_p.size(); i++) {
s_p.set(i, "U");
}
//Collections.reverse(d_p);
ArrayList<String> ans = new ArrayList<>(s_p);
ans.addAll(d_p);
return ans;
}
public static void main(String[] args)
{
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;
ArrayList<String> ans
= getDirections(root, startValue, endValue);
System.out.println(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.
C#
// C# code for the above approach
using System;
using System.Collections.Generic;
public class TreeNode {
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int val2)
{
this.val = val2;
this.left = null;
this.right = null;
}
}
public class GFG {
// Find function
static bool Find(TreeNode n, int val, List<string> path)
{
if (n.val == val) {
return true;
}
if (n.left != null && Find(n.left, val, path)) {
path.Add("R");
return true;
}
if (n.right != null && Find(n.right, val, path)) {
path.Add("L");
return true;
}
return false;
}
// Function to keep track of directions at any point
static List<string> GetDirections(TreeNode root,
int startValue,
int destValue)
{
// To store the startPath and destPath
var s_p = new List<string>();
var d_p = new List<string>();
Find(root, startValue, s_p);
Find(root, destValue, d_p);
while (s_p.Count > 0 && d_p.Count > 0
&& s_p[s_p.Count - 1]
== d_p[d_p.Count - 1]) {
s_p.RemoveAt(s_p.Count - 1);
d_p.RemoveAt(d_p.Count - 1);
}
for (int i = 0; i < s_p.Count; i++) {
s_p[i] = "U";
}
// Collections.reverse(d_p)
var ans = new List<string>(s_p);
ans.AddRange(d_p);
return ans;
}
static public void Main()
{
// Code
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;
var ans = GetDirections(root, startValue, endValue);
Console.WriteLine(string.Join("", ans));
}
}
// This code is contributed by karthik.
JavaScript
// JavaScript Code
class TreeNode {
constructor(val2) {
this.val = val2;
this.left = null;
this.right = null;
}
}
// Find Function
function find(n, val, path) {
if (n.val === val) {
return true;
}
if (n.left && find(n.left, val, path)) {
path.push("L");
return true;
}
if (n.right && find(n.right, val, path)) {
path.push("R");
return true;
}
return false;
}
// Function to keep track of directions at any point
function getDirections(root, startValue, destValue) {
// To store the startPath and destPath
let s_p = [],
d_p = [];
find(root, startValue, s_p);
find(root, destValue, d_p);
while (s_p.length && d_p.length && s_p[s_p.length - 1] === d_p[d_p.length - 1]) {
s_p.pop();
d_p.pop();
}
for (let i = 0; i < s_p.length; i++) {
s_p[i] = "U";
}
d_p.reverse();
let ans = s_p.concat(d_p);
return ans;
}
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;
let ans = getDirections(root, startValue, endValue);
console.log(ans);
// This code is contributed by vinayetbi1.
Time complexity: O(N)
Auxiliary Space: O(N)
Similar Reads
Path from the root node to a given node in an N-ary Tree Given an integer N and an N-ary Tree of the following form: Every node is numbered sequentially, starting from 1, till the last level, which contains the node N.The nodes at every odd level contains 2 children and nodes at every even level contains 4 children. The task is to print the path from the
10 min read
Print path from a node to root of given Complete Binary Tree Given an integer N, the task is to find the path from the Nth node to the root of a Binary Tree of the following form: The Binary Tree is a Complete Binary Tree up to the level of the Nth node.The nodes are numbered 1 to N, starting from the root as 1.The structure of the Tree is as follows: 1 / \ 2
4 min read
Minimum edges to reverse to make path from a source to a destination Given a directed graph with n nodes and m edges. A source node and a destination node are also given, we need to find how many edges we need to reverse in order to make at least 1 path from the source node to the destination node.Note: In case there is no way then return -1.Examples:  Input: n = 7,
15+ min read
Queries to calculate sum of the path from root to a given node in given Binary Tree Given an infinite complete binary tree rooted at node 1, where every ith node has two children, with values 2 * i and 2 * (i + 1). Given another array arr[] consisting of N positive integers, the task for each array element arr[i] is to find the sum of the node values that occur in a path from the r
10 min read
Monotonic shortest path from source to destination in Directed Weighted Graph Given a weighted directed graph with N vertices and M edges, a source src and a destination target, the task is to find the shortest monotonic path (monotonically increasing or decreasing) from the source to the destination. Output -1 if no monotonic path is possible. Note: All weights are non-negat
14 min read
Find distance from root to given node in a binary tree Given the root of a binary tree and a key x in it, find the distance of the given key from the root. DisÂtance means the numÂber of edges between two nodes.Examples: Input: x = 45Input Binary TreeOutput: 3 Explanation: There are three edges on path from root to 45.For more understanding of question,
11 min read