Count Nodes at Distance K From Leaf

Last Updated : 19 Jul, 2026

Given a binary tree with nodes and a non-negative integer k, the task is to count the number of special nodes.

  • A node is considered special if there exists at least one leaf in its subtree such that the distance between the node and leaf is exactly k.
  • Any such node should be counted only once. For example, if a node is at a distance k from 2 or more leaf nodes, then it would add only 1 to the count.

Examples:

Input: root[] = [1, 2, 3, 4, 5, 6, 7, N, N, N, N, N, 8], k = 2

7

Output: 2
Explanation: There are only two unique nodes that are at a distance of 2 units from the leaf node. (node 3 for leaf with value 8 and node 1 for leaves with values 4, 5 and 7) Note that node 2 isn't considered for leaf with value 8 because it isn't a direct ancestor of node 8.

Try It Yourself
redirect icon

[Naive Approach] Check Every Node Separately - O(n ^ 2) Time and O(h) Space

The idea is to consider every node as a starting node and check whether there exists a leaf in its subtree at exactly distance k. If such a leaf exists, increment the answer.

Working of Approach:

  • Traverse every node of the binary tree using DFS, treating each node as a potential starting point.
  • For each node, recursively search its subtree to check whether there exists a leaf exactly k edges below it.
C++
#include <iostream>
using namespace std;

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

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

// Returns true if there is a leaf exactly k edges below node.
bool check(Node *root, int dist, int k)
{
    if (!root)
        return false;

    // Leaf node
    if (!root->left && !root->right)
        return dist == k;

    return check(root->left, dist + 1, k) || check(root->right, dist + 1, k);
}

// Visit every node and check it separately.
void dfs(Node *root, int k, int &ans)
{
    if (!root)
        return;

    if (check(root, 0, k))
        ans++;

    dfs(root->left, k, ans);
    dfs(root->right, k, ans);
}

int kthFromLeaf(Node *root, int k)
{
    int ans = 0;
    dfs(root, k, ans);
    return ans;
}

int main()
{

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

    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->right->left->right = new Node(8);

    int k = 2;

    cout << kthFromLeaf(root, k);

    return 0;
}
Java
class Node {
    int data;
    Node left, right;

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

class GFG {

    // Returns true if there is a leaf exactly k edges below
    // node.
    static boolean check(Node root, int dist, int k)
    {
        if (root == null)
            return false;

        // Leaf node
        if (root.left == null && root.right == null)
            return dist == k;

        return check(root.left, dist + 1, k)
            || check(root.right, dist + 1, k);
    }

    // Visit every node and check it separately.
    static void dfs(Node root, int k, int[] ans)
    {
        if (root == null)
            return;

        if (check(root, 0, k))
            ans[0]++;

        dfs(root.left, k, ans);
        dfs(root.right, k, ans);
    }

    static int kthFromLeaf(Node root, int k)
    {
        int[] ans = { 0 };
        dfs(root, k, ans);
        return ans[0];
    }

    public static void main(String[] args)
    {

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

        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.right.left.right = new Node(8);

        int k = 2;

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


# Returns true if there is a leaf exactly k edges below node.
def check(root, dist, k):
    if root is None:
        return False

    # Leaf node
    if root.left is None and root.right is None:
        return dist == k

    return check(root.left, dist + 1, k) or check(root.right, dist + 1, k)


# Visit every node and check it separately.
def dfs(root, k, ans):
    if root is None:
        return

    if check(root, 0, k):
        ans[0] += 1

    dfs(root.left, k, ans)
    dfs(root.right, k, ans)


def kthFromLeaf(root, k):
    ans = [0]
    dfs(root, k, ans)
    return ans[0]


if __name__ == "__main__":

    """
              1
            /   \
           2     3
          / \   / \
         4   5 6   7
                \
                 8
    """

    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.right.left.right = Node(8)

    k = 2

    print(kthFromLeaf(root, k))
C#
using System;

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

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

class GFG {
    // Returns true if there is a leaf exactly k edges below
    // node.
    static bool Check(Node root, int dist, int k)
    {
        if (root == null)
            return false;

        // Leaf node
        if (root.left == null && root.right == null)
            return dist == k;

        return Check(root.left, dist + 1, k)
            || Check(root.right, dist + 1, k);
    }

    // Visit every node and check it separately.
    static void Dfs(Node root, int k, ref int ans)
    {
        if (root == null)
            return;

        if (Check(root, 0, k))
            ans++;

        Dfs(root.left, k, ref ans);
        Dfs(root.right, k, ref ans);
    }

    static int kthFromLeaf(Node root, int k)
    {
        int ans = 0;
        Dfs(root, k, ref ans);
        return ans;
    }

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

        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.right.left.right = new Node(8);

        int k = 2;

        Console.WriteLine(kthFromLeaf(root, k));
    }
}
JavaScript
// Returns true if there is a leaf exactly k edges below
// node.
function check(root, dist, k)
{
    if (root === null)
        return false;

    // Leaf node
    if (root.left === null && root.right === null)
        return dist === k;

    return check(root.left, dist + 1, k)
           || check(root.right, dist + 1, k);
}

// Visit every node and check it separately.
function dfs(root, k, ans)
{
    if (root === null)
        return;

    if (check(root, 0, k))
        ans.count++;

    dfs(root.left, k, ans);
    dfs(root.right, k, ans);
}

function kthFromLeaf(root, k)
{
    let ans = {count : 0};
    dfs(root, k, ans);
    return ans.count;
}

// Helper function to create a node
function newNode(val)
{
    return {data : val, left : null, right : null};
}

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

let root = newNode(1);

root.left = newNode(2);
root.right = newNode(3);

root.left.left = newNode(4);
root.left.right = newNode(5);

root.right.left = newNode(6);
root.right.right = newNode(7);

root.right.left.right = newNode(8);

let k = 2;

console.log(kthFromLeaf(root, k));

Output
2

[Expected Approach] Single DFS with Path Level Marking - O(n) Time and O(h) Space

The idea is to perform a DFS while maintaining the current root-to-node path. Whenever a leaf is reached, its k-th ancestor is found using the current path. A visited[] array indexed by the current path level ensures that the same ancestor is counted only once, even if multiple leaf nodes share the same k-th ancestor.

Working of Approach:

  • Traverse the binary tree using DFS, while maintaining the current path length from the root to the current node.
  • Whenever a leaf node is reached, its k-th ancestor is located using the index pathLen - k - 1.
  • A visited[] array is used to mark ancestors that have already been counted, preventing duplicate counting when multiple leaves share the same k-th ancestor.
  • Continue the DFS for both left and right subtrees until all root-to-leaf paths have been explored.
  • The final counter gives the number of unique nodes that are exactly k distance away from at least one leaf node.

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

  • Start the DFS from the root (1) with pathLen = 0, recursively exploring all root-to-leaf paths.
  • On reaching leaf nodes 4 and 5, their 2nd ancestor is node 1; it is counted only once by marking its level as visited.
  • Next, the traversal reaches leaf node 8, whose 2nd ancestor is node 3; since it has not been counted before, increment the counter.
  • Finally, for leaf node 7, the 2nd ancestor is again node 1, which is already marked, so it is not counted again.
  • After all paths are processed, the counter becomes 2, representing the unique nodes (1 and 3) that are exactly 2 distance away from at least one leaf node.
C++
#include <iostream>
using namespace std;

#define MAX_HEIGHT 100005

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

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

void countNodes(Node *node, Node *path[], int &counter, bool visited[],
                int pathLen, int k)
{
    // base case
    if (node == nullptr)
        return;

    path[pathLen] = node;
    visited[pathLen] = false;
    pathLen++;

    // if it's a leaf node, we increment the count but only if the
    // same ancestor at distance k is not already counted.
    if (node->left == nullptr && node->right == nullptr &&
        pathLen - k - 1 >= 0 &&
        visited[pathLen - k - 1] == false)
    {
        counter++;

        // setting the ancestor as visited so that we won't count it again.
        visited[pathLen - k - 1] = true;
        return;
    }

    // if the current node is not a leaf node then we call the function
    // recursively for left and right subtrees.
    countNodes(node->left, path, counter, visited, pathLen, k);
    countNodes(node->right, path, counter, visited, pathLen, k);
}

// Function to return count of nodes at a given distance from leaf nodes.
int kthFromLeaf(Node *root, int k)
{
    int counter = 0;
    bool visited[MAX_HEIGHT] = {false};
    Node *path[MAX_HEIGHT];

    countNodes(root, path, counter, visited, 0, k);

    // returning the count.
    return counter;
}

int main()
{
    /*
              1
            /   \
           2     3
          / \   / \
         4   5 6   7
                \
                 8
    */

    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->right->left->right = new Node(8);

    int k = 2;

    cout << kthFromLeaf(root, k);

    return 0;
}
Java
class Node {
    int data;
    Node left, right;

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

class GFG {

    static final int MAX_HEIGHT = 100005;

    static void countNodes(Node node, Node[] path,
                           int[] counter, boolean[] visited,
                           int pathLen, int k)
    {
        // base case
        if (node == null)
            return;

        path[pathLen] = node;
        visited[pathLen] = false;
        pathLen++;

        // if it's a leaf node, we increment the count but
        // only if the same ancestor at distance k is not
        // already counted.
        if (node.left == null && node.right == null
            && pathLen - k - 1 >= 0
            && visited[pathLen - k - 1] == false) {

            counter[0]++;

            // setting the ancestor as visited so that we
            // won't count it again.
            visited[pathLen - k - 1] = true;
            return;
        }

        // if the current node is not a leaf node then we
        // call the function recursively for left and right
        // subtrees.
        countNodes(node.left, path, counter, visited,
                   pathLen, k);
        countNodes(node.right, path, counter, visited,
                   pathLen, k);
    }

    // Function to return count of nodes at a given distance
    // from leaf nodes.
    static int kthFromLeaf(Node root, int k)
    {
        int[] counter = { 0 };
        boolean[] visited = new boolean[MAX_HEIGHT];
        Node[] path = new Node[MAX_HEIGHT];

        countNodes(root, path, counter, visited, 0, k);

        // returning the count.
        return counter[0];
    }

    public static void main(String[] args)
    {

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

        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.right.left.right = new Node(8);

        int k = 2;

        System.out.println(kthFromLeaf(root, k));
    }
}
Python
MAX_HEIGHT = 100005


class Node:
    def __init__(self, val):
        self.data = val
        self.left = None
        self.right = None


def countNodes(node, path, counter, visited, pathLen, k):
    # base case
    if node is None:
        return

    path[pathLen] = node
    visited[pathLen] = False
    pathLen += 1

    # if it's a leaf node, we increment the count but only if the
    # same ancestor at distance k is not already counted.
    if (node.left is None and node.right is None and
        pathLen - k - 1 >= 0 and
            visited[pathLen - k - 1] == False):

        counter[0] += 1

        # setting the ancestor as visited so that we won't count it again.
        visited[pathLen - k - 1] = True
        return

    # if the current node is not a leaf node then we call the function
    # recursively for left and right subtrees.
    countNodes(node.left, path, counter, visited, pathLen, k)
    countNodes(node.right, path, counter, visited, pathLen, k)


# Function to return count of nodes at a given distance from leaf nodes.
def kthFromLeaf(root, k):
    counter = [0]
    visited = [False] * MAX_HEIGHT
    path = [None] * MAX_HEIGHT

    countNodes(root, path, counter, visited, 0, k)

    # returning the count.
    return counter[0]


if __name__ == "__main__":

    """
              1
            /   \
           2     3
          / \   / \
         4   5 6   7
                \
                 8
    """

    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.right.left.right = Node(8)

    k = 2

    print(kthFromLeaf(root, k))
C#
using System;

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

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

class GFG {
    const int MAX_HEIGHT = 100005;

    static void CountNodes(Node node, Node[] path,
                           ref int counter, bool[] visited,
                           int pathLen, int k)
    {
        // base case
        if (node == null)
            return;

        path[pathLen] = node;
        visited[pathLen] = false;
        pathLen++;

        // if it's a leaf node, we increment the count but
        // only if the same ancestor at distance k is not
        // already counted.
        if (node.left == null && node.right == null
            && pathLen - k - 1 >= 0
            && visited[pathLen - k - 1] == false) {
            counter++;

            // setting the ancestor as visited so that we
            // won't count it again.
            visited[pathLen - k - 1] = true;
            return;
        }

        // if the current node is not a leaf node then we
        // call the function recursively for left and right
        // subtrees.
        CountNodes(node.left, path, ref counter, visited,
                   pathLen, k);
        CountNodes(node.right, path, ref counter, visited,
                   pathLen, k);
    }

    // Function to return count of nodes at a given distance
    // from leaf nodes.
    static int kthFromLeaf(Node root, int k)
    {
        int counter = 0;
        bool[] visited = new bool[MAX_HEIGHT];
        Node[] path = new Node[MAX_HEIGHT];

        CountNodes(root, path, ref counter, visited, 0, k);

        // returning the count.
        return counter;
    }

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

        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.right.left.right = new Node(8);

        int k = 2;

        Console.WriteLine(kthFromLeaf(root, k));
    }
}
JavaScript
const MAX_HEIGHT = 100005;

function newNode(val)
{
    return {data : val, left : null, right : null};
}

function countNodes(node, path, counter, visited, pathLen,
                    k)
{
    // base case
    if (node === null)
        return;

    path[pathLen] = node;
    visited[pathLen] = false;
    pathLen++;

    // if it's a leaf node, we increment the count but only
    // if the same ancestor at distance k is not already
    // counted.
    if (node.left === null && node.right === null
        && pathLen - k - 1 >= 0
        && visited[pathLen - k - 1] === false) {

        counter.count++;

        // setting the ancestor as visited so that we won't
        // count it again.
        visited[pathLen - k - 1] = true;
        return;
    }

    // if the current node is not a leaf node then we call
    // the function recursively for left and right subtrees.
    countNodes(node.left, path, counter, visited, pathLen,
               k);
    countNodes(node.right, path, counter, visited, pathLen,
               k);
}

// Function to return count of nodes at a given distance
// from leaf nodes.
function kthFromLeaf(root, k)
{
    let counter = {count : 0};
    let visited = new Array(MAX_HEIGHT).fill(false);
    let path = new Array(MAX_HEIGHT);

    countNodes(root, path, counter, visited, 0, k);

    // returning the count.
    return counter.count;
}

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

let root = newNode(1);

root.left = newNode(2);
root.right = newNode(3);

root.left.left = newNode(4);
root.left.right = newNode(5);

root.right.left = newNode(6);
root.right.right = newNode(7);

root.right.left.right = newNode(8);

let k = 2;

console.log(kthFromLeaf(root, k));

Output
2
Comment