Number of turns to reach from one node to other in binary tree

Last Updated : 20 Aug, 2026

Given root of a binary tree and the values of its two nodes p and q, count turns required to travel from node p to q.

  • A turn occurs whenever the direction of movement changes from left to right or right to left while traversing the tree.
  • If the path between the two nodes does not involve any turns (i.e., the nodes lie on the same straight path), return -1.

Note: All node values are distinct.

Examples: 

Input: root[] = [1, 2, 3, 4, 5, 6, 7, 8, N, N, N, 9, 10], p = 5, q = 10

1

Output: 4
Explanation: The path from node 5 to node 10 is: 5 -> 2 -> 1 -> 3 -> 6 → 10. Direction changes occur at nodes 2, 1, 3, and 6. Therefore, the number of turns is 4.

Input: root[] = [1, 2, 3, 4, 5, 6, 7, 8, N, N, N, 9, 10], p = 1, q = 4

2

Output: -1
Explanation: No turn is required since they are in a straight line.

Try It Yourself
redirect icon

[Naive Approach] Find Complete Path - O(n) Time and O(n) Space

The idea is to find the path from the root to both p and q.

Combine these paths to construct the complete path from p to q.

After that, we check every consecutive pair and count whenever the direction changes from left to right or right to left.

Working of the Approach:

  • Find the path from root to p and root to q.
  • Find their common path to identify the LCA.
  • Construct the complete path from p to q.
  • For every edge, identify whether it represents a left or right direction.
  • Count direction changes and return -1 if there are no turns.
C++
#include <iostream>
#include <vector>
using namespace std;

class Node
{
  public:
    int data;
    Node *left;
    Node *right;

    Node(int val)
    {
        data = val;
        left = right = nullptr;
    }
};

// Find path from root to the target node
bool findPath(Node *root, int target, vector<Node *> &path)
{

    if (root == nullptr)
        return false;

    path.push_back(root);

    // Target node found
    if (root->data == target)
        return true;

    // Search in left subtree
    if (findPath(root->left, target, path))
        return true;

    // Search in right subtree
    if (findPath(root->right, target, path))
        return true;

    // Remove current node if target is not found
    path.pop_back();

    return false;
}

int numberOfTurns(Node *root, int p, int q)
{

    vector<Node *> pathP, pathQ;

    // Find paths from root to p and q
    findPath(root, p, pathP);
    findPath(root, q, pathQ);

    // Find the common part of both paths
    int i = 0;

    while (i < pathP.size() && i < pathQ.size() && pathP[i] == pathQ[i])
    {
        i++;
    }

    // Build complete path from p to q
    vector<Node *> path;

    // Add path from p to LCA
    for (int j = pathP.size() - 1; j >= i - 1; j--)
        path.push_back(pathP[j]);

    // Add path from LCA to q
    for (int j = i; j < pathQ.size(); j++)
        path.push_back(pathQ[j]);

    int turns = 0;
    int prevDir = 0;

    // Count changes between left and right directions
    for (int j = 0; j + 1 < path.size(); j++)
    {

        int currDir;

        // Moving from parent to left child
        if (path[j]->left == path[j + 1])
            currDir = 1;

        // Moving from parent to right child
        else if (path[j]->right == path[j + 1])
            currDir = 2;

        // Moving from child to parent
        else if (path[j + 1]->left == path[j])
            currDir = 1;

        else
            currDir = 2;

        // Direction changed
        if (prevDir != 0 && prevDir != currDir)
            turns++;

        prevDir = currDir;
    }

    // If no turn is present, return -1
    return turns == 0 ? -1 : turns;
}

int main()
{

    /*
              1
            /   \
           2     3
          / \   / \
         4   5 6   7
        /       / \
       8       9  10

        p = 5
        q = 10
    */

    Node *root = new Node(1);

    root->left = new Node(2);
    root->right = new Node(3);

    root->left->left = new Node(4);
    root->left->right = new Node(5);

    root->right->left = new Node(6);
    root->right->right = new Node(7);

    root->left->left->left = new Node(8);

    root->right->left->left = new Node(9);
    root->right->left->right = new Node(10);

    int p = 5;
    int q = 10;

    cout << numberOfTurns(root, p, q) << endl;

    return 0;
}
Java
import java.util.ArrayList;
import java.util.List;

class Node {
    public int data;
    public Node left;
    public Node right;

    public Node(int val)
    {
        data = val;
        left = right = null;
    }
}

public class GFG {
    // Find path from root to the target node
    public static boolean findPath(Node root, int target,
                                   List<Node> path)
    {
        if (root == null)
            return false;

        path.add(root);

        // Target node found
        if (root.data == target)
            return true;

        // Search in left subtree
        if (findPath(root.left, target, path))
            return true;

        // Search in right subtree
        if (findPath(root.right, target, path))
            return true;

        // Remove current node if target is not found
        path.remove(path.size() - 1);

        return false;
    }

    public static int numberOfTurns(Node root, int p, int q)
    {
        List<Node> pathP = new ArrayList<>(),
                   pathQ = new ArrayList<>();

        // Find paths from root to p and q
        findPath(root, p, pathP);
        findPath(root, q, pathQ);

        // Find the common part of both paths
        int i = 0;

        while (i < pathP.size() && i < pathQ.size()
               && pathP.get(i) == pathQ.get(i)) {
            i++;
        }

        // Build complete path from p to q
        List<Node> path = new ArrayList<>();

        // Add path from p to LCA
        for (int j = pathP.size() - 1; j >= i - 1; j--)
            path.add(pathP.get(j));

        // Add path from LCA to q
        for (int j = i; j < pathQ.size(); j++)
            path.add(pathQ.get(j));

        int turns = 0;
        int prevDir = 0;

        // Count changes between left and right directions
        for (int j = 0; j + 1 < path.size(); j++) {

            int currDir;

            // Moving from parent to left child
            if (path.get(j).left == path.get(j + 1))
                currDir = 1;

            // Moving from parent to right child
            else if (path.get(j).right == path.get(j + 1))
                currDir = 2;

            // Moving from child to parent
            else if (path.get(j + 1).left == path.get(j))
                currDir = 1;

            else
                currDir = 2;

            // Direction changed
            if (prevDir != 0 && prevDir != currDir)
                turns++;

            prevDir = currDir;
        }

        // If no turn is present, return -1
        return turns == 0 ? -1 : turns;
    }

    public static void main(String[] args)
    {
        Node root = new Node(1);

        root.left = new Node(2);
        root.right = new Node(3);

        root.left.left = new Node(4);
        root.left.right = new Node(5);

        root.right.left = new Node(6);
        root.right.right = new Node(7);

        root.left.left.left = new Node(8);

        root.right.left.left = new Node(9);
        root.right.left.right = new Node(10);

        int p = 5;
        int q = 10;

        System.out.println(numberOfTurns(root, p, q));
    }
}
Python
class Node:
    def __init__(self, val):
        self.data = val
        self.left = None
        self.right = None

# Find path from root to the target node


def findPath(root, target, path):
    if root is None:
        return False

    path.append(root)

    # Target node found
    if root.data == target:
        return True

    # Search in left subtree
    if findPath(root.left, target, path):
        return True

    # Search in right subtree
    if findPath(root.right, target, path):
        return True

    # Remove current node if target is not found
    path.pop()

    return False


def numberOfTurns(root, p, q):
    pathP, pathQ = [], []

    # Find paths from root to p and q
    findPath(root, p, pathP)
    findPath(root, q, pathQ)

    # Find the common part of both paths
    i = 0
    while i < len(pathP) and i < len(pathQ) and pathP[i] == pathQ[i]:
        i += 1

    # Build complete path from p to q
    path = []

    # Add path from p to LCA
    for j in range(len(pathP) - 1, i - 2, -1):
        path.append(pathP[j])

    # Add path from LCA to q
    for j in range(i, len(pathQ)):
        path.append(pathQ[j])

    turns = 0
    prevDir = 0

    # Count changes between left and right directions
    for j in range(len(path) - 1):

        currDir = 0

        # Moving from parent to left child
        if path[j].left == path[j + 1]:
            currDir = 1

        # Moving from parent to right child
        elif path[j].right == path[j + 1]:
            currDir = 2

        # Moving from child to parent
        elif path[j + 1].left == path[j]:
            currDir = 1
        else:
            currDir = 2

        # Direction changed
        if prevDir != 0 and prevDir != currDir:
            turns += 1

        prevDir = currDir

    # If no turn is present, return -1
    return -1 if turns == 0 else turns


if __name__ == '__main__':
    root = Node(1)

    root.left = Node(2)
    root.right = Node(3)

    root.left.left = Node(4)
    root.left.right = Node(5)

    root.right.left = Node(6)
    root.right.right = Node(7)

    root.left.left.left = Node(8)

    root.right.left.left = Node(9)
    root.right.left.right = Node(10)

    p = 5
    q = 10

    print(numberOfTurns(root, p, q))
C#
using System;
using System.Collections.Generic;

public class Node {
    public int data;
    public Node left;
    public Node right;

    public Node(int val)
    {
        data = val;
        left = right = null;
    }
}

public class GFG {
    // Find path from root to the target node
    public static bool findPath(Node root, int target,
                                List<Node> path)
    {
        if (root == null)
            return false;

        path.Add(root);

        // Target node found
        if (root.data == target)
            return true;

        // Search in left subtree
        if (findPath(root.left, target, path))
            return true;

        // Search in right subtree
        if (findPath(root.right, target, path))
            return true;

        // Remove current node if target is not found
        path.RemoveAt(path.Count - 1);

        return false;
    }

    public static int numberOfTurns(Node root, int p, int q)
    {
        List<Node> pathP = new List<Node>(),
                   pathQ = new List<Node>();

        // Find paths from root to p and q
        findPath(root, p, pathP);
        findPath(root, q, pathQ);

        // Find the common part of both paths
        int i = 0;

        while (i < pathP.Count && i < pathQ.Count
               && pathP[i] == pathQ[i]) {
            i++;
        }

        // Build complete path from p to q
        List<Node> path = new List<Node>();

        // Add path from p to LCA
        for (int j = pathP.Count - 1; j >= i - 1; j--)
            path.Add(pathP[j]);

        // Add path from LCA to q
        for (int j = i; j < pathQ.Count; j++)
            path.Add(pathQ[j]);

        int turns = 0;
        int prevDir = 0;

        // Count changes between left and right directions
        for (int j = 0; j + 1 < path.Count; j++) {
            int currDir;

            // Moving from parent to left child
            if (path[j].left == path[j + 1])
                currDir = 1;

            // Moving from parent to right child
            else if (path[j].right == path[j + 1])
                currDir = 2;

            // Moving from child to parent
            else if (path[j + 1].left == path[j])
                currDir = 1;

            else
                currDir = 2;

            // Direction changed
            if (prevDir != 0 && prevDir != currDir)
                turns++;

            prevDir = currDir;
        }

        // If no turn is present, return -1
        return turns == 0 ? -1 : turns;
    }

    public static void Main()
    {
        /*
              1
            /   \
           2     3
          / \   / \\
         4   5 6   7
        /       / \\
       8       9  10

        p = 5
        q = 10
        */

        Node root = new Node(1);

        root.left = new Node(2);
        root.right = new Node(3);

        root.left.left = new Node(4);
        root.left.right = new Node(5);

        root.right.left = new Node(6);
        root.right.right = new Node(7);

        root.left.left.left = new Node(8);

        root.right.left.left = new Node(9);
        root.right.left.right = new Node(10);

        int p = 5;
        int q = 10;

        Console.WriteLine(numberOfTurns(root, p, q));
    }
}
JavaScript
class Node {
    constructor(val)
    {
        this.data = val;
        this.left = null;
        this.right = null;
    }
}

// Find path from root to the target node
function findPath(root, target, path)
{
    if (root === null)
        return false;

    path.push(root);

    // Target node found
    if (root.data === target)
        return true;

    // Search in left subtree
    if (findPath(root.left, target, path))
        return true;

    // Search in right subtree
    if (findPath(root.right, target, path))
        return true;

    // Remove current node if target is not found
    path.pop();

    return false;
}

function numberOfTurns(root, p, q)
{
    let pathP = [], pathQ = [];

    // Find paths from root to p and q
    findPath(root, p, pathP);
    findPath(root, q, pathQ);

    // Find the common part of both paths
    let i = 0;

    while (i < pathP.length && i < pathQ.length
           && pathP[i] === pathQ[i]) {
        i++;
    }

    // Build complete path from p to q
    let path = [];

    // Add path from p to LCA
    for (let j = pathP.length - 1; j >= i - 1; j--)
        path.push(pathP[j]);

    // Add path from LCA to q
    for (let j = i; j < pathQ.length; j++)
        path.push(pathQ[j]);

    let turns = 0;
    let prevDir = 0;

    // Count changes between left and right directions
    for (let j = 0; j + 1 < path.length; j++) {
        let currDir;

        // Moving from parent to left child
        if (path[j].left === path[j + 1])
            currDir = 1;

        // Moving from parent to right child
        else if (path[j].right === path[j + 1])
            currDir = 2;

        // Moving from child to parent
        else if (path[j + 1].left === path[j])
            currDir = 1;

        else
            currDir = 2;

        // Direction changed
        if (prevDir !== 0 && prevDir !== currDir)
            turns++;

        prevDir = currDir;
    }

    // If no turn is present, return -1
    return turns === 0 ? -1 : turns;
}

// Driver Code
let root = new Node(1);

root.left = new Node(2);
root.right = new Node(3);

root.left.left = new Node(4);
root.left.right = new Node(5);

root.right.left = new Node(6);
root.right.right = new Node(7);

root.left.left.left = new Node(8);

root.right.left.left = new Node(9);
root.right.left.right = new Node(10);

let p = 5;
let q = 10;

console.log(numberOfTurns(root, p, q));

Output
4

[Expected Approach] Using LCA with Path Tracking - O(n) Time and O(n) Space

The idea is to first find the LCA of p and q, then find the paths from the LCA to both nodes using L and R.

We count direction changes in both paths.

If p and q are in different subtrees of the LCA, moving from one subtree to the other creates one additional turn.

Working of the Approach:

  • Find the LCA of p and q.
  • Find the L/R path from LCA to p and from LCA to q.
  • Count direction changes in both paths.
  • If LCA is neither p nor q, add one turn for changing subtrees at LCA.
  • Return -1 if the total number of turns is 0.

Let us understand with an example:
Input: root[] = [1, 2, 3, 4, 5, 6, 7, 8, N, N, N, 9, 10], p = 5, q = 10

1
  • Find LCA: The LCA of nodes 5 and 10 is 1.
  • Find paths from LCA: Path to 5 is LR, and path to 10 is RLR.
  • Count turns: LR has 1 turn, while RLR has 2 turns.
  • Turn at LCA: Since 5 and 10 are in different subtrees of 1, add 1 extra turn.
  • Total: 1 + 2 + 1 = 4, so the answer is 4.
C++
#include <iostream>
#include <vector>
#include <string>
using namespace std;

class Node
{
  public:
    int data;
    Node *left;
    Node *right;

    Node(int val)
    {
        data = val;
        left = right = nullptr;
    }
};

// Finds LCA of two given nodes
Node *findLCA(Node *root, int p, int q)
{
    if (root == nullptr)
        return nullptr;

    if (root->data == p || root->data == q)
        return root;

    Node *left = findLCA(root->left, p, q);
    Node *right = findLCA(root->right, p, q);

    if (left && right)
        return root;

    return left ? left : right;
}

// Stores path from root to target node using L/R directions
bool findPath(Node *root, int target, string &path)
{
    if (root == nullptr)
        return false;

    if (root->data == target)
        return true;

    // Try going left
    path.push_back('L');
    if (findPath(root->left, target, path))
        return true;
    path.pop_back();

    // Try going right
    path.push_back('R');
    if (findPath(root->right, target, path))
        return true;
    path.pop_back();

    return false;
}

// Counts direction changes in a path
int countTurns(string &path)
{
    int turns = 0;

    for (int i = 1; i < path.length(); i++)
    {
        if (path[i] != path[i - 1])
            turns++;
    }

    return turns;
}

// Returns number of turns required from first node to second node
int numberOfTurns(Node *root, int p, int q)
{

    Node *lca = findLCA(root, p, q);

    if (lca == nullptr)
        return -1;

    string pathFirst = "";
    string pathSecond = "";

    // Paths from LCA to both nodes
    findPath(lca, p, pathFirst);
    findPath(lca, q, pathSecond);

    int turns = 0;

    /*
    If LCA is one of the nodes, there is no extra
    turn at LCA because we start from that node.
    */
    if (lca->data == p || lca->data == q)
    {

        string path = (lca->data == p) ? pathSecond : pathFirst;

        turns = countTurns(path);
    }

    else
    {

        /*
        We go:
        first -> LCA -> second

        At LCA, we change direction from one subtree
        to another, so it contributes one turn.
        */
        turns = countTurns(pathFirst) + countTurns(pathSecond) + 1;
    }

    // No turns means both nodes lie on a straight path
    return turns == 0 ? -1 : turns;
}

int main()
{

    /*
              1
            /   \
           2     3
          / \   / \
         4   5 6   7
        /       / \
       8       9  10

        p = 5
        q = 10
    */

    Node *root = new Node(1);

    root->left = new Node(2);
    root->right = new Node(3);

    root->left->left = new Node(4);
    root->left->right = new Node(5);

    root->right->left = new Node(6);
    root->right->right = new Node(7);

    root->left->left->left = new Node(8);

    root->right->left->left = new Node(9);
    root->right->left->right = new Node(10);

    int p = 5;
    int q = 10;

    cout << numberOfTurns(root, p, q) << endl;

    return 0;
}
Java
import java.util.*;

class Node {
    public int data;
    public Node left;
    public Node right;

    public Node(int val)
    {
        data = val;
        left = right = null;
    }
}

public class GFG {
    // Finds LCA of two given nodes
    static Node findLCA(Node root, int p, int q)
    {
        if (root == null)
            return null;

        if (root.data == p || root.data == q)
            return root;

        Node left = findLCA(root.left, p, q);
        Node right = findLCA(root.right, p, q);

        if (left != null && right != null)
            return root;

        return left != null ? left : right;
    }

    // Stores path from root to target node using L/R
    // directions
    static boolean findPath(Node root, int target,
                            StringBuilder path)
    {
        if (root == null)
            return false;

        if (root.data == target)
            return true;

        // Try going left
        path.append('L');
        if (findPath(root.left, target, path))
            return true;
        path.deleteCharAt(path.length() - 1);

        // Try going right
        path.append('R');
        if (findPath(root.right, target, path))
            return true;
        path.deleteCharAt(path.length() - 1);

        return false;
    }

    // Counts direction changes in a path
    static int countTurns(String path)
    {
        int turns = 0;

        for (int i = 1; i < path.length(); i++) {
            if (path.charAt(i) != path.charAt(i - 1))
                turns++;
        }

        return turns;
    }

    // Returns number of turns required from first node to
    // second node
    static int numberOfTurns(Node root, int p, int q)
    {

        Node lca = findLCA(root, p, q);

        if (lca == null)
            return -1;

        StringBuilder pathFirst = new StringBuilder();
        StringBuilder pathSecond = new StringBuilder();

        // Paths from LCA to both nodes
        findPath(lca, p, pathFirst);
        findPath(lca, q, pathSecond);

        int turns = 0;

        /*
        If LCA is one of the nodes, there is no extra
        turn at LCA because we start from that node.
        */
        if (lca.data == p || lca.data == q) {

            String path = (lca.data == p)
                              ? pathSecond.toString()
                              : pathFirst.toString();

            turns = countTurns(path);
        }

        else {

            /*
            We go:
            first -> LCA -> second

            At LCA, we change direction from one subtree
            to another, so it contributes one turn.
            */
            turns = countTurns(pathFirst.toString())
                    + countTurns(pathSecond.toString()) + 1;
        }

        // No turns means both nodes lie on a straight path
        return turns == 0 ? -1 : turns;
    }

    public static void main(String[] args)
    {
        /*
                  1
                /   \
               2     3
              / \   / \
             4   5 6   7
            /       / \
           8       9  10

            p = 5
            q = 10
        */

        Node root = new Node(1);

        root.left = new Node(2);
        root.right = new Node(3);

        root.left.left = new Node(4);
        root.left.right = new Node(5);

        root.right.left = new Node(6);
        root.right.right = new Node(7);

        root.left.left.left = new Node(8);

        root.right.left.left = new Node(9);
        root.right.left.right = new Node(10);

        int p = 5;
        int q = 10;

        System.out.println(numberOfTurns(root, p, q));
    }
}
Python
class Node:
    def __init__(self, val):
        self.data = val
        self.left = None
        self.right = None


# Finds LCA of two given nodes
def findLCA(root, p, q):

    if root is None:
        return None

    if root.data == p or root.data == q:
        return root

    left = findLCA(root.left, p, q)
    right = findLCA(root.right, p, q)

    if left and right:
        return root

    return left if left else right


# Stores path from root to target node using L/R directions
def findPath(root, target, path):

    if root is None:
        return False

    if root.data == target:
        return True

    # Try going left
    path.append('L')

    if findPath(root.left, target, path):
        return True

    path.pop()

    # Try going right
    path.append('R')

    if findPath(root.right, target, path):
        return True

    path.pop()

    return False


# Counts direction changes in a path
def countTurns(path):

    turns = 0

    for i in range(1, len(path)):

        if path[i] != path[i - 1]:
            turns += 1

    return turns


# Returns number of turns required from first node to second node
def numberOfTurns(root, p, q):

    lca = findLCA(root, p, q)

    if lca is None:
        return -1

    pathFirst = []
    pathSecond = []

    # Paths from LCA to both nodes
    findPath(lca, p, pathFirst)
    findPath(lca, q, pathSecond)

    if lca.data == p or lca.data == q:

        path = pathSecond if lca.data == p else pathFirst

        turns = countTurns(path)

    else:

        # Add one turn for changing direction at LCA
        turns = (countTurns(pathFirst) +
                 countTurns(pathSecond) + 1)

    # No turns means straight path
    return -1 if turns == 0 else turns


if __name__ == "__main__":

    #             1
    #           /   \
    #          2     3
    #         / \   / \
    #        4   5 6   7
    #       /       / \
    #      8       9  10
    #
    #      p = 5
    #      q = 10

    root = Node(1)

    root.left = Node(2)
    root.right = Node(3)

    root.left.left = Node(4)
    root.left.right = Node(5)

    root.right.left = Node(6)
    root.right.right = Node(7)

    root.left.left.left = Node(8)

    root.right.left.left = Node(9)
    root.right.left.right = Node(10)

    p = 5
    q = 10

    print(numberOfTurns(root, p, q))
C#
using System;
using System.Text;

public class Node {
    public int data;
    public Node left;
    public Node right;

    public Node(int val)
    {
        data = val;
        left = right = null;
    }
}

public class GFG {
    // Finds LCA of two given nodes
    public static Node findLCA(Node root, int p, int q)
    {
        if (root == null)
            return null;

        if (root.data == p || root.data == q)
            return root;

        Node left = findLCA(root.left, p, q);
        Node right = findLCA(root.right, p, q);

        if (left != null && right != null)
            return root;

        return left ? ? right;
    }

    // Stores path from root to target node using L/R
    // directions
    public static bool findPath(Node root, int target,
                                StringBuilder path)
    {
        if (root == null)
            return false;

        if (root.data == target)
            return true;

        // Try going left
        path.Append('L');
        if (findPath(root.left, target, path))
            return true;
        path.Length--;

        // Try going right
        path.Append('R');
        if (findPath(root.right, target, path))
            return true;
        path.Length--;

        return false;
    }

    // Counts direction changes in a path
    public static int countTurns(string path)
    {
        int turns = 0;

        for (int i = 1; i < path.Length; i++) {
            if (path[i] != path[i - 1])
                turns++;
        }

        return turns;
    }

    // Returns number of turns required from first node to
    // second node
    public static int numberOfTurns(Node root, int p, int q)
    {
        Node lca = findLCA(root, p, q);

        if (lca == null)
            return -1;

        StringBuilder pathFirst = new StringBuilder();
        StringBuilder pathSecond = new StringBuilder();

        // Paths from LCA to both nodes
        findPath(lca, p, pathFirst);
        findPath(lca, q, pathSecond);

        int turns = 0;

        /*
        If LCA is one of the nodes, there is no extra
        turn at LCA because we start from that node.
        */
        if (lca.data == p || lca.data == q) {
            string path = (lca.data == p)
                              ? pathSecond.ToString()
                              : pathFirst.ToString();

            turns = countTurns(path);
        }

        else {
            /*
            We go:
            first -> LCA -> second

            At LCA, we change direction from one subtree
            to another, so it contributes one turn.
            */
            turns = countTurns(pathFirst.ToString())
                    + countTurns(pathSecond.ToString()) + 1;
        }

        // No turns means both nodes lie on a straight path
        return turns == 0 ? -1 : turns;
    }

    public static void Main()
    {
        /*
                  1
                /   \
               2     3
              / \   / \
             4   5 6   7
            /       / \
           8       9  10

            p = 5
            q = 10
        */

        Node root = new Node(1);

        root.left = new Node(2);
        root.right = new Node(3);

        root.left.left = new Node(4);
        root.left.right = new Node(5);

        root.right.left = new Node(6);
        root.right.right = new Node(7);

        root.left.left.left = new Node(8);

        root.right.left.left = new Node(9);
        root.right.left.right = new Node(10);

        int p = 5;
        int q = 10;

        Console.WriteLine(numberOfTurns(root, p, q));
    }
}
JavaScript
class Node {
    constructor(val)
    {
        this.data = val;
        this.left = null;
        this.right = null;
    }
}

// Finds LCA of two given nodes
function findLCA(root, p, q)
{
    if (!root)
        return null;

    if (root.data === p || root.data === q)
        return root;

    const left = findLCA(root.left, p, q);
    const right = findLCA(root.right, p, q);

    if (left && right)
        return root;

    return left || right;
}

// Stores path from root to target node using L/R directions
function findPath(root, target, path)
{
    if (!root)
        return false;

    if (root.data === target)
        return true;

    // Try going left
    path.push("L");
    if (findPath(root.left, target, path))
        return true;
    path.pop();

    // Try going right
    path.push("R");
    if (findPath(root.right, target, path))
        return true;
    path.pop();

    return false;
}

// Counts direction changes in a path
function countTurns(path)
{
    let turns = 0;

    for (let i = 1; i < path.length; i++) {
        if (path[i] !== path[i - 1])
            turns++;
    }

    return turns;
}

// Returns number of turns required from first node to
// second node
function numberOfTurns(root, p, q)
{
    const lca = findLCA(root, p, q);

    if (!lca)
        return -1;

    const pathFirst = [];
    const pathSecond = [];

    // Paths from LCA to both nodes
    findPath(lca, p, pathFirst);
    findPath(lca, q, pathSecond);

    let turns = 0;

    /*
    If LCA is one of the nodes, there is no extra
    turn at LCA because we start from that node.
    */
    if (lca.data === p || lca.data === q) {
        const path
            = (lca.data === p) ? pathSecond : pathFirst;
        turns = countTurns(path);
    }
    else {
        /*
        We go:
        first -> LCA -> second

        At LCA, we change direction from one subtree
        to another, so it contributes one turn.
        */
        turns = countTurns(pathFirst)
                + countTurns(pathSecond) + 1;
    }

    // No turns means both nodes lie on a straight path
    return turns === 0 ? -1 : turns;
}

// Driver Code
/*
          1
        /   \
       2     3
      / \   / \
     4   5 6   7
    /       / \
   8       9  10

    p = 5
    q = 10
*/

const root = new Node(1);

root.left = new Node(2);
root.right = new Node(3);

root.left.left = new Node(4);
root.left.right = new Node(5);

root.right.left = new Node(6);
root.right.right = new Node(7);

root.left.left.left = new Node(8);

root.right.left.left = new Node(9);
root.right.left.right = new Node(10);

const p = 5;
const q = 10;

console.log(numberOfTurns(root, p, q));

Output
4
Comment