Open In App

Print all nodes that are at distance k from a leaf node

Improve
Improve
Like Article
Like
Save
Share
Report

Given a Binary Tree and a positive integer K, print all nodes that are distance K from a leaf node. Here K distance from a leaf means K levels higher than a leaf node. For example, if K is more than the height of the Binary Tree, then nothing should be printed. 

Examples:

distKfromLeaf

Recommended Practice

Approach: To solve the problem follow the below idea: 

We can store the nodes in the path of our recursion and whenever we reach a leaf node, then print the Kth node in the saved path

Follow the below steps to solve the problem:

  • Traverse the tree and keep storing all ancestors till we hit a leaf node. 
  • When we reach a leaf node, we print the ancestor at distance K using the values stored in the array. 
  • We also need to keep track of nodes that are already printed as output. For that, we use a boolean array visited[]

Below is the implementation of the above approach:

C++




/* C++ Program to print all nodes
which are at distance k from a leaf */
#include <iostream>
using namespace std;
#define MAX_HEIGHT 10000
 
struct Node {
    int key;
    Node *left, *right;
};
 
/* utility that allocates a new Node with the given key  */
Node* newNode(int key)
{
    Node* node = new Node;
    node->key = key;
    node->left = node->right = NULL;
    return (node);
}
 
/* This function prints all nodes that are distance k from a
   leaf node path[] --> Store ancestors of a node visited[]
   --> Stores true if a node is printed as output.  A node
   may be k
                 distance away from many leaves, we want to
   print it once */
void kDistantFromLeafUtil(Node* node, int path[],
                          bool visited[], int pathLen,
                          int k)
{
    // Base case
    if (node == NULL)
        return;
 
    /* append this Node to the path array */
    path[pathLen] = node->key;
    visited[pathLen] = false;
    pathLen++;
 
    /* it's a leaf, so print the ancestor at distance k only
       if the ancestor is not already printed  */
    if (node->left == NULL && node->right == NULL
        && pathLen - k - 1 >= 0
        && visited[pathLen - k - 1] == false) {
        cout << path[pathLen - k - 1] << " ";
        visited[pathLen - k - 1] = true;
        return;
    }
 
    /* If not leaf node, recur for left and right subtrees
     */
    kDistantFromLeafUtil(node->left, path, visited, pathLen,
                         k);
    kDistantFromLeafUtil(node->right, path, visited,
                         pathLen, k);
}
 
/* Given a binary tree and a number k, print all nodes that
   are k distant from a leaf*/
void printKDistantfromLeaf(Node* node, int k)
{
    int path[MAX_HEIGHT];
    bool visited[MAX_HEIGHT] = { false };
    kDistantFromLeafUtil(node, path, visited, 0, k);
}
 
/* Driver code*/
int main()
{
    // Let us create binary tree
    // given in the above example
    Node* 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);
 
    cout << "Nodes at distance 2 are: ";
    printKDistantfromLeaf(root, 2);
 
    return 0;
}


Java




// Java program to print all nodes at a distance k from leaf
// A binary tree node
class Node {
    int data;
    Node left, right;
 
    Node(int item)
    {
        data = item;
        left = right = null;
    }
}
 
class BinaryTree {
    Node root;
 
    /* This function prints all nodes that are distance k
     from a leaf node path[] --> Store ancestors of a node
     visited[] --> Stores true if a node is printed as
     output.  A node may be k distance away from many
     leaves, we want to print it once */
    void kDistantFromLeafUtil(Node node, int path[],
                              boolean visited[],
                              int pathLen, int k)
    {
        // Base case
        if (node == null)
            return;
 
        /* append this Node to the path array */
        path[pathLen] = node.data;
        visited[pathLen] = false;
        pathLen++;
 
        /* it's a leaf, so print the ancestor at distance k
         only if the ancestor is not already printed  */
        if (node.left == null && node.right == null
            && pathLen - k - 1 >= 0
            && visited[pathLen - k - 1] == false) {
            System.out.print(path[pathLen - k - 1] + " ");
            visited[pathLen - k - 1] = true;
            return;
        }
 
        /* If not leaf node, recur for left and right
         * subtrees */
        kDistantFromLeafUtil(node.left, path, visited,
                             pathLen, k);
        kDistantFromLeafUtil(node.right, path, visited,
                             pathLen, k);
    }
 
    /* Given a binary tree and a number k, print all nodes
     that are k distant from a leaf*/
    void printKDistantfromLeaf(Node node, int k)
    {
        int path[] = new int[1000];
        boolean visited[] = new boolean[1000];
        kDistantFromLeafUtil(node, path, visited, 0, k);
    }
 
    // Driver code
    public static void main(String args[])
    {
        BinaryTree tree = new BinaryTree();
 
        /* Let us construct the tree shown in above diagram
         */
        tree.root = new Node(1);
        tree.root.left = new Node(2);
        tree.root.right = new Node(3);
        tree.root.left.left = new Node(4);
        tree.root.left.right = new Node(5);
        tree.root.right.left = new Node(6);
        tree.root.right.right = new Node(7);
        tree.root.right.left.right = new Node(8);
 
        System.out.print(" Nodes at distance 2 are : ");
        tree.printKDistantfromLeaf(tree.root, 2);
    }
}
 
// This code has been contributed by Mayank Jaiswal


Python3




# Program to print all nodes which are at
# distance k from a leaf
 
# utility that allocates a new Node with
# the given key
 
 
class newNode:
    def __init__(self, key):
        self.key = key
        self.left = self.right = None
 
# This function prints all nodes that
# are distance k from a leaf node
# path[] -. Store ancestors of a node
# visited[] -. Stores true if a node is
# printed as output. A node may be k distance
# away from many leaves, we want to print it once
 
 
def kDistantFromLeafUtil(node, path, visited,
                         pathLen, k):
 
    # Base case
    if (node == None):
        return
 
    # append this Node to the path array
    path[pathLen] = node.key
    visited[pathLen] = False
    pathLen += 1
 
    # it's a leaf, so print the ancestor at
    # distance k only if the ancestor is
    # not already printed
    if (node.left == None and node.right == None and
        pathLen - k - 1 >= 0 and
            visited[pathLen - k - 1] == False):
        print(path[pathLen - k - 1], end=" ")
        visited[pathLen - k - 1] = True
        return
 
    # If not leaf node, recur for left
    # and right subtrees
    kDistantFromLeafUtil(node.left, path,
                         visited, pathLen, k)
    kDistantFromLeafUtil(node.right, path,
                         visited, pathLen, k)
 
# Given a binary tree and a number k,
# print all nodes that are k distant from a leaf
 
 
def printKDistantfromLeaf(node, k):
    global MAX_HEIGHT
    path = [None] * MAX_HEIGHT
    visited = [False] * MAX_HEIGHT
    kDistantFromLeafUtil(node, path, visited, 0, k)
 
 
# Driver Code
MAX_HEIGHT = 10000
 
# Let us create binary tree given in
# the above example
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)
 
print("Nodes at distance 2 are:", end=" ")
printKDistantfromLeaf(root, 2)
 
# This code is contributed by pranchalK


C#




using System;
 
// C# program to print all nodes at a distance k from leaf
// A binary tree node
public class Node {
    public int data;
    public Node left, right;
 
    public Node(int item)
    {
        data = item;
        left = right = null;
    }
}
 
public class BinaryTree {
    public Node root;
 
    /* This function prints all nodes that are distance k
     from a leaf node path[] --> Store ancestors of a node
     visited[] --> Stores true if a node is printed as
     output.  A node may be k distance away from many
     leaves, we want to print it once */
    public virtual void
    kDistantFromLeafUtil(Node node, int[] path,
                         bool[] visited, int pathLen, int k)
    {
        // Base case
        if (node == null) {
            return;
        }
 
        /* append this Node to the path array */
        path[pathLen] = node.data;
        visited[pathLen] = false;
        pathLen++;
 
        /* it's a leaf, so print the ancestor at distance k
         only if the ancestor is not already printed  */
        if (node.left == null && node.right == null
            && pathLen - k - 1 >= 0
            && visited[pathLen - k - 1] == false) {
            Console.Write(path[pathLen - k - 1] + " ");
            visited[pathLen - k - 1] = true;
            return;
        }
 
        /* If not leaf node, recur for left and right
         * subtrees */
        kDistantFromLeafUtil(node.left, path, visited,
                             pathLen, k);
        kDistantFromLeafUtil(node.right, path, visited,
                             pathLen, k);
    }
 
    /* Given a binary tree and a number k, print all nodes
     that are k distant from a leaf*/
    public virtual void printKDistantfromLeaf(Node node,
                                              int k)
    {
        int[] path = new int[1000];
        bool[] visited = new bool[1000];
        kDistantFromLeafUtil(node, path, visited, 0, k);
    }
 
    // Driver program to test the above functions
    public static void Main(string[] args)
    {
        BinaryTree tree = new BinaryTree();
 
        /* Let us construct the tree shown in above diagram
         */
        tree.root = new Node(1);
        tree.root.left = new Node(2);
        tree.root.right = new Node(3);
        tree.root.left.left = new Node(4);
        tree.root.left.right = new Node(5);
        tree.root.right.left = new Node(6);
        tree.root.right.right = new Node(7);
        tree.root.right.left.right = new Node(8);
 
        Console.Write(" Nodes at distance 2 are : ");
        tree.printKDistantfromLeaf(tree.root, 2);
    }
}
 
// This code is contributed by Shrikant13


Javascript




<script>
 
    // JavaScript program to print all
    // nodes at a distance k from leaf
    // A binary tree node
     
    class Node
    {
        constructor(item) {
           this.left = null;
           this.right = null;
           this.data = item;
        }
    }
     
    let root;
  
    /* This function prints all nodes that
       are distance k from a leaf node
       path[] --> Store ancestors of a node
       visited[] --> Stores true if a node is
       printed as output.  A node may
       be k distance away from many leaves,
       we want to print it once */
    function kDistantFromLeafUtil(node, path, visited, pathLen, k)
    {
        // Base case
        if (node == null)
            return;
  
        /* append this Node to the path array */
        path[pathLen] = node.data;
        visited[pathLen] = false;
        pathLen++;
  
        /* it's a leaf, so print the ancestor at distance k only
         if the ancestor is not already printed  */
        if (node.left == null && node.right == null
            && (pathLen - k - 1) >= 0 &&
            visited[pathLen - k - 1] == false) {
            document.write(path[pathLen - k - 1] + " ");
            visited[pathLen - k - 1] = true;
            return;
        }
  
        /* If not leaf node, recur for left and right subtrees */
        kDistantFromLeafUtil(node.left, path, visited, pathLen, k);
        kDistantFromLeafUtil(node.right, path, visited, pathLen, k);
    }
  
    /* Given a binary tree and a number k, print all nodes that are k
     distant from a leaf*/
    function printKDistantfromLeaf(node, k)
    {
        let path = new Array(1000);
        path.fill(0);
        let visited = new Array(1000);
        visited.fill(false);
        kDistantFromLeafUtil(node, path, visited, 0, k);
    }
     
    /* Let us construct the tree shown in above diagram */
    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);
 
    document.write(" Nodes at distance 2 are : ");
    printKDistantfromLeaf(root, 2);
     
</script>


Output

Nodes at distance 2 are: 1 3 










Time Complexity: O(N)
Auxiliary Space: O(N)

Approach 2: Iterative Solution

In this approach, we use an iterative method to traverse the binary tree using a stack. We maintain a stack of pairs, where each pair consists of a node and its depth. We start by pushing the root node and its depth onto the stack. Then, we repeatedly pop a node from the stack and push its left and right children, along with their depths, onto the stack. When we encounter a leaf node, we check its depth and see if it is at a distance k from the current node. If it is, we print the current node.

  • Initialize an empty stack st, an empty vector path, and an empty vector visited.
  • Push a pair (root, 0) onto the stack, where root is the root of the binary tree and 0 is the depth of root.
  • While st is not empty, do the following:
    •  Pop the top pair (curr, depth) from st.
    • If curr is nullptr, continue to the next iteration of the loop.
    • Append curr->val to path and false to visited.
    • If curr is a leaf node, check if its depth is k less than the current depth of curr. If so, check if the node at that depth has already been visited. If not, print the value of the node at that depth and mark it as visited.
    • Push the pairs (curr->left, depth + 1) and (curr->right, depth + 1) onto st.
    • If depth + 1 is less than the size of path, resize path and visited to remove the nodes beyond depth + 1.

Here’s the codes for this approach:

C++




#include <iostream>
#include <stack>
#include <vector>
using namespace std;
 
struct Node {
    int val;
    Node *left, *right;
    Node(int v) : val(v), left(nullptr), right(nullptr) {}
};
 
void printKDist(Node* root, int k) {
    stack<pair<Node*, int>> st;
    vector<int> path;
    vector<bool> visited;
    st.push(make_pair(root, 0));
 
    while (!st.empty()) {
        pair<Node*, int> curr = st.top();
        st.pop();
 
        if (curr.first == nullptr) {
            continue;
        }
 
        path.push_back(curr.first->val);
        visited.push_back(false);
 
        if (curr.first->left == nullptr && curr.first->right == nullptr) {
            int depth = path.size() - 1 - k;
            if (depth >= 0 && !visited[depth]) {
                cout << path[depth] << " ";
                visited[depth] = true;
            }
        }
 
        st.push(make_pair(curr.first->left, curr.second + 1));
        st.push(make_pair(curr.first->right, curr.second + 1));
 
        if (curr.second + 1 < path.size()) {
            path.resize(curr.second + 1);
            visited.resize(curr.second + 1);
        }
    }
}
 
int main() {
    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);
 
    printKDist(root, 2);
 
    return 0;
}


Java




import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
 
class Node {
    int val;
    Node left, right;
 
    Node(int v)
    {
        val = v;
        left = null;
        right = null;
    }
}
 
public class GFG {
    // Function to print nodes at a distance 'k' from the
    // root
    public static void printKDist(Node root, int k)
    {
        Stack<Pair> stack = new Stack<>();
        List<Integer> path = new ArrayList<>();
        List<Boolean> visited = new ArrayList<>();
        stack.push(new Pair(root, 0));
 
        while (!stack.isEmpty()) {
            Pair curr = stack.pop();
 
            if (curr.node == null) {
                continue; // Skip null nodes
            }
 
            path.add(curr.node.val);
            visited.add(false);
 
            // If the current node is a leaf node and at the
            // correct depth
            if (curr.node.left == null
                && curr.node.right == null) {
                int depth = path.size() - 1 - k;
                if (depth >= 0 && !visited.get(depth)) {
                    System.out.print(
                        path.get(depth)
                        + " "); // Print the node value
                    visited.set(depth, true);
                }
            }
 
            // Push the left and right child nodes onto the
            // stack
            stack.push(
                new Pair(curr.node.left, curr.depth + 1));
            stack.push(
                new Pair(curr.node.right, curr.depth + 1));
 
            // Trim the path and visited lists to the
            // current depth
            if (curr.depth + 1 < path.size()) {
                int newSize = curr.depth + 1;
                path.subList(newSize, path.size()).clear();
                visited.subList(newSize, visited.size())
                    .clear();
            }
        }
    }
 
    public static void main(String[] args)
    {
        // Create a sample tree
        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);
 
        // Call the function to print nodes at distance 2
        // from the root
        printKDist(root, 2);
    }
}
 
class Pair {
    Node node;
    int depth;
 
    Pair(Node n, int d)
    {
        node = n;
        depth = d;
    }
}
 
// This code is contributed by Taranpreet Singh.


Python3




# Node class representing a binary tree node
class Node:
    def __init__(self, val):
        self.val = val
        self.left = None
        self.right = None
 
# Function to print nodes at k distance from the leaves of
# the binary tree
def printKDist(root, k):
    stack = []
    path = []
    visited = []
    stack.append([root, 0])
 
    # Until the stack is not empty
    while stack:
        curr, depth = stack.pop()
 
        # If curr node is None, continue for other nodes
        if curr is None:
            continue
 
        path.append(curr.val)
        visited.append(False)
 
        if curr.left is None and curr.right is None:
            dist = len(path) - 1 - k
            if dist >= 0 and not visited[dist]:
                print(path[dist])
                visited[dist] = True
 
        stack.append([curr.left, depth + 1])
        stack.append([curr.right, depth + 1])
 
        if depth + 1 < len(path):
            path = path[:depth + 1]
            visited = visited[:depth + 1]
 
# Driver code to test the above function
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)
 
printKDist(root, 2)


C#




using System;
using System.Collections.Generic;
 
namespace ConsoleApp1
{
    class Program
    {
        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.right.left.right = new Node(8);
 
            printKDist(root, 2);
 
            Console.ReadKey();
        }
         
        // Function to print nodes at k distance from the leaves of
        // the binary tree
        static void printKDist(Node root, int k)
        {
            // Create a stack to store node-depth pairs
            Stack<Tuple<Node, int>> st = new Stack<Tuple<Node, int>>();
            List<int> path = new List<int>(); // Stores the path values
            List<bool> visited = new List<bool>(); // Tracks visited nodes in the path
            st.Push(new Tuple<Node, int>(root, 0)); // Push the root node and depth 0
 
            while (st.Count > 0)
            {
                Tuple<Node, int> curr = st.Pop(); // Pop the current node-depth pair
 
                if (curr.Item1 == null)
                {
                    continue; // Skip null nodes
                }
 
                path.Add(curr.Item1.val);
                visited.Add(false);
 
                if (curr.Item1.left == null && curr.Item1.right == null)
                {
                    int depth = path.Count - 1 - k;
                    if (depth >= 0 && !visited[depth])
                    {
                        Console.Write(path[depth] + " ");
                        visited[depth] = true;
                    }
                }
 
                st.Push(new Tuple<Node, int>(curr.Item1.left, curr.Item2 + 1));
                st.Push(new Tuple<Node, int>(curr.Item1.right, curr.Item2 + 1));
 
                if (curr.Item2 + 1 < path.Count)
                {
                    // Remove nodes beyond the current depth
                    path.RemoveRange(curr.Item2 + 1, path.Count - curr.Item2 - 1);
                    visited.RemoveRange(curr.Item2 + 1, visited.Count - curr.Item2 - 1);
                }
            }
        }
    }
 
    class Node
    {
        public int val;
        public Node left;
        public Node right;
 
        public Node(int v)
        {
            val = v;
            left = null;
            right = null;
        }
    }
}


Javascript




// Node class representing a binary tree node
class Node {
  constructor(val) {
    this.val = val;
    this.left = null;
    this.right = null;
  }
}
 
// Function to print nodes at k distance from the leaves of
// the binary tree
function printKDist(root, k) {
  const stack = [];
  const path = [];
  const visited = [];
  stack.push([root, 0]);
 
  // Until the stack is not empty
  while (stack.length > 0) {
    const [curr, depth] = stack.pop();
     
    // if curr node is NULL then continue for other nodes
    if (curr === null) {
      continue;
    }
 
    path.push(curr.val);
    visited.push(false);
 
    if (curr.left === null && curr.right === null) {
      const dist = path.length - 1 - k;
      if (dist >= 0 && !visited[dist]) {
        console.log(path[dist]);
        visited[dist] = true;
      }
    }
 
    stack.push([curr.left, depth + 1]);
    stack.push([curr.right, depth + 1]);
 
    if (depth + 1 < path.length) {
      path.length = depth + 1;
      visited.length = depth + 1;
    }
  }
}
 
// Driver code to test above function
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.right.left.right = new Node(8);
 
printKDist(root, 2);
// THIS CODE IS CONTRIBUTED BY YASH AGARWAL(YASHAGARWAL2852002)


Output

1 3 










Time Complexity:
In the worst case, we visit every node in the binary tree once. For each node, we append its value to path and false to visited, which takes O(1) time. If the node is a leaf node, we check its depth and mark the corresponding node in visited if necessary, which also takes O(1) time. Finally, we push its left and right children onto st, which takes O(1) time each. Thus, the time complexity of the algorithm is O(n), where n is the number of nodes in the binary tree.

Space Complexity:
The space used by the algorithm is proportional to the maximum depth of the binary tree. In the worst case, the binary tree is a skewed tree, in which case the maximum depth is n. In this case, the size of path and visited is O(n), and the size of the stack st is also O(n). Thus, the space complexity of the algorithm is O(n). However, in the best case, the binary tree is a balanced tree, in which case the maximum depth is log(n). In this case, the space complexity is O(log(n)).



Last Updated : 16 Oct, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads