Count of leaf nodes required to be removed at each step to empty a given Binary Tree

Last Updated : 23 Jun, 2026

Given the root of a binary tree of size n, repeatedly remove all leaf nodes in each operation and return an array containing the count of leaf nodes removed at every step.

Examples:

Input: 

2056958382

Output: 4 2 1 1 
Explanation: 
In the 1st operation removing the leaf nodes { 1, 3, 4, 6 } from the binary tree. 
In the 2nd operation removing the leaf nodes { 8, 7 } 
In the 3rd operation removing the leaf nodes { 5 } 
In the 4th operation removing the leaf nodes { 2 } 
Therefore, the count of leaf nodes removed in each operation 4 2 1 1.

Input: 

blobid3_1781953723

Output: 2 1
Explanation:
In the 1st operation, leaf nodes {3,2} are removed.
In the 2nd operation, leaf nodes {1} are removed.
Therefore, the count of leaf nodes removed in each operation is 2 1.

[Naive Approach] Repeated DFS Simulation for Leaf Removal - O(n^2) Time and O(h) Space

The idea is to repeatedly remove all leaf nodes from the binary tree and record their count at each step. In each iteration, we traverse the tree, delete current leaf nodes, and update the structure. Since removing leaves creates new leaves, the process continues until the tree becomes empty. Finally, we return the count of nodes removed in each iteration.

C++
#include <bits/stdc++.h>
using namespace std;

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

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

// Helper function to remove all leaf nodes in one pass
Node* removeLeaves(Node* root, int &cnt) {
    if (!root) return nullptr;

    // If current node is a leaf
    if (!root->left && !root->right) {
        cnt++;
        delete root;
        return nullptr;
    }

    root->left = removeLeaves(root->left, cnt);
    root->right = removeLeaves(root->right, cnt);

    return root;
}

vector<int> emptyTree(Node* root) {
    vector<int> ans;

    while (root) {
        int cnt = 0;

        root = removeLeaves(root, cnt);

        ans.push_back(cnt);
    }

    return ans;
}

int main() {

    // Tree structure:
    //          2
    //        /   \
    //       5     7
    //      / \     \
    //     1   8     6
    //        / \
    //       3   4

    Node* root = new Node(2);
    root->left = new Node(5);
    root->right = new Node(7);
    root->right->right = new Node(6);
    root->left->left = new Node(1);
    root->left->right = new Node(8);
    root->left->right->left = new Node(3);
    root->left->right->right = new Node(4);

    vector<int> res = emptyTree(root);

    for (int x : res) {
        cout << x << " ";
    }

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

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

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

public class GFG {

    // Helper function to remove all leaf nodes in one pass
    static Node removeLeaves(Node root, int[] cnt) {
        if (root == null) return null;

        // If current node is a leaf
        if (root.left == null && root.right == null) {
            cnt[0]++;
            return null;
        }

        root.left = removeLeaves(root.left, cnt);
        root.right = removeLeaves(root.right, cnt);

        return root;
    }

    static ArrayList<Integer> emptyTree(Node root) {
        ArrayList<Integer> ans = new ArrayList<>();

        while (root != null) {
            int[] cnt = new int[1];

            root = removeLeaves(root, cnt);

            ans.add(cnt[0]);
        }

        return ans;
    }

    public static void main(String[] args) {

        // Tree structure:
        //          2
        //        /   \
        //       5     7
        //      / \     \
        //     1   8     6
        //        / \
        //       3   4

        Node root = new Node(2);
        root.left = new Node(5);
        root.right = new Node(7);
        root.right.right = new Node(6);
        root.left.left = new Node(1);
        root.left.right = new Node(8);
        root.left.right.left = new Node(3);
        root.left.right.right = new Node(4);

        ArrayList<Integer> res = emptyTree(root);

        for (int x : res) {
            System.out.print(x + " ");
        }
    }
}
Python
class Node:
    def __init__(self, val):
        self.data = val
        self.left = None
        self.right = None

# Helper function to remove all leaf nodes in one pass
def removeLeaves(root, cnt):
    if not root:
        return None

    # If current node is a leaf
    if not root.left and not root.right:
        cnt[0] += 1
        return None

    root.left = removeLeaves(root.left, cnt)
    root.right = removeLeaves(root.right, cnt)

    return root


def emptyTree(root):
    ans = []

    while root:
        cnt = [0]

        root = removeLeaves(root, cnt)

        ans.append(cnt[0])

    return ans


if __name__ == "__main__":

    # Tree structure:
    #          2
    #        /   \
    #       5     7
    #      / \     \
    #     1   8     6
    #        / \
    #       3   4

    root = Node(2)
    root.left = Node(5)
    root.right = Node(7)
    root.right.right = Node(6)
    root.left.left = Node(1)
    root.left.right = Node(8)
    root.left.right.left = Node(3)
    root.left.right.right = Node(4)

    res = emptyTree(root)

    for x in res:
        print(x, end=" ")
C#
using System;
using System.Collections.Generic;

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

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

class GFG {

    // Helper function to remove all leaf nodes in one pass
    static Node removeLeaves(Node root, ref int cnt) {
        if (root == null) return null;

        // If current node is a leaf
        if (root.left == null && root.right == null) {
            cnt++;
            return null;
        }

        root.left = removeLeaves(root.left, ref cnt);
        root.right = removeLeaves(root.right, ref cnt);

        return root;
    }

    static List<int> emptyTree(Node root) {
        List<int> ans = new List<int>();

        while (root != null) {
            int cnt = 0;

            root = removeLeaves(root, ref cnt);

            ans.Add(cnt);
        }

        return ans;
    }

    static void Main(string[] args) {

        // Tree structure:
        //          2
        //        /   \
        //       5     7
        //      / \     \
        //     1   8     6
        //        / \
        //       3   4

        Node root = new Node(2);
        root.left = new Node(5);
        root.right = new Node(7);
        root.right.right = new Node(6);
        root.left.left = new Node(1);
        root.left.right = new Node(8);
        root.left.right.left = new Node(3);
        root.left.right.right = new Node(4);

        List<int> res = emptyTree(root);

        foreach (int x in res) {
            Console.Write(x + " ");
        }
    }
}
JavaScript
class Node {
    constructor(val) {
        this.data = val;
        this.left = null;
        this.right = null;
    }
}

// Helper function to remove all leaf nodes in one pass
function removeLeaves(root, cnt) {
    if (root === null) return null;

    // If current node is a leaf
    if (root.left === null && root.right === null) {
        cnt.count++;
        return null;
    }

    root.left = removeLeaves(root.left, cnt);
    root.right = removeLeaves(root.right, cnt);

    return root;
}

function emptyTree(root) {
    let ans = [];

    while (root !== null) {
        let cnt = { count: 0 };

        root = removeLeaves(root, cnt);

        ans.push(cnt.count);
    }

    return ans;
}

// Driver code

// Tree structure:
//          2
//        /   \
//       5     7
//      / \     \
//     1   8     6
//        / \
//       3   4

let root = new Node(2);
root.left = new Node(5);
root.right = new Node(7);
root.right.right = new Node(6);
root.left.left = new Node(1);
root.left.right = new Node(8);
root.left.right.left = new Node(3);
root.left.right.right = new Node(4);

let res = emptyTree(root);

console.log(res.join(" "));

Output
4 2 1 1 

[Expected Approach] Group Nodes by Height Using DFS Traversal - O(n) Time and O(n) Space

Instead of repeatedly removing leaf nodes, we observe that each node is deleted based on its height from the bottom (leaf level). All nodes with the same height are removed in the same operation.

So, we compute the height of each node using DFS and group nodes by height. The size of each group gives the number of nodes removed in each step.

  • Traverse the binary tree using DFS.
  • For each node, compute its height as: height = 1 + max(leftHeight, rightHeight)
  • Store nodes in a map where: Key is height and Value is list of nodes at that height
  • Iterate the map in increasing order of height.
  • For each group, add its size to the result array.
C++
#include <bits/stdc++.h>
using namespace std;

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

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

// Returns the height of the current node
// and groups nodes having the same height.
int getHeight(Node *root, map<int, vector<int>> &mp)
{

    if (root == nullptr)
        return 0;

    // Height of left subtree
    int lh = getHeight(root->left, mp);

    // Height of right subtree
    int rh = getHeight(root->right, mp);

    // Height of current node
    int ht = 1 + max(lh, rh);

    // Store current node at its height level
    mp[ht].push_back(root->data);

    return ht;
}

vector<int> emptyTree(Node *root)
{

    // Stores the number of nodes removed
    // in each iteration
    vector<int> res;

    // Maps height -> nodes at that height
    map<int, vector<int>> mp;

    // Group nodes by height
    getHeight(root, mp);

    // Nodes with the same height are removed
    // in the same iteration
    for (auto &it : mp)
    {
        res.push_back(it.second.size());
    }

    return res;
}

int main()
{

    // Tree structure:
    //          2
    //        /   \
    //       5     7
    //      / \     \
    //     1   8     6
    //        / \
    //       3   4

    Node *root = new Node(2);
    root->left = new Node(5);
    root->right = new Node(7);
    root->right->right = new Node(6);
    root->left->left = new Node(1);
    root->left->right = new Node(8);
    root->left->right->left = new Node(3);
    root->left->right->right = new Node(4);

    vector<int> res = emptyTree(root);

    for (int x : res)
    {
        cout << x << " ";
    }

    return 0;
}
Java
import java.util.ArrayList;
import java.util.Map;
import java.util.TreeMap;

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

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

public class GFG
{

    // Returns the height of the current node
    // and groups nodes having the same height.
    static int getHeight(Node root, Map<Integer, ArrayList<Integer>> mp)
    {

        if (root == null)
            return 0;

        // Height of left subtree
        int lh = getHeight(root.left, mp);

        // Height of right subtree
        int rh = getHeight(root.right, mp);

        // Height of current node
        int ht = 1 + Math.max(lh, rh);

        // Store current node at its height level
        mp.putIfAbsent(ht, new ArrayList<>());
        mp.get(ht).add(root.data);

        return ht;
    }

    static ArrayList<Integer> emptyTree(Node root)
    {

        // Stores the number of nodes removed
        // in each iteration
        ArrayList<Integer> res = new ArrayList<>();

        // Maps height -> nodes at that height
        Map<Integer, ArrayList<Integer>> mp = new TreeMap<>();

        // Group nodes by height
        getHeight(root, mp);

        // Nodes with the same height are removed
        // in the same iteration
        for (Map.Entry<Integer, ArrayList<Integer>> it : mp.entrySet())
        {
            res.add(it.getValue().size());
        }

        return res;
    }

    public static void main(String[] args)
    {

        // Tree structure:
        //          2
        //        /   \
        //       5     7
        //      / \     \
        //     1   8     6
        //        / \
        //       3   4

        Node root = new Node(2);
        root.left = new Node(5);
        root.right = new Node(7);
        root.right.right = new Node(6);
        root.left.left = new Node(1);
        root.left.right = new Node(8);
        root.left.right.left = new Node(3);
        root.left.right.right = new Node(4);

        ArrayList<Integer> res = emptyTree(root);

        for (int x : res)
        {
            System.out.print(x + " ");
        }
    }
}
Python
class Node:
    def __init__(self, val):
        self.data = val
        self.left = None
        self.right = None

# Returns the height of the current node
# and groups nodes having the same height.
def getHeight(root, mp):

    if root is None:
        return 0

    # Height of left subtree
    lh = getHeight(root.left, mp)

    # Height of right subtree
    rh = getHeight(root.right, mp)

    # Height of current node
    ht = 1 + max(lh, rh)

    # Store current node at its height level
    if ht not in mp:
        mp[ht] = []
    mp[ht].append(root.data)

    return ht


def emptyTree(root):

    # Stores the number of nodes removed
    # in each iteration
    res = []

    # Maps height -> nodes at that height
    mp = {}

    # Group nodes by height
    getHeight(root, mp)

    # Nodes with the same height are removed
    # in the same iteration
    for key in sorted(mp.keys()):
        res.append(len(mp[key]))

    return res


if __name__ == "__main__":

    # Tree structure:
    #          2
    #        /   \
    #       5     7
    #      / \     \
    #     1   8     6
    #        / \
    #       3   4

    root = Node(2)
    root.left = Node(5)
    root.right = Node(7)
    root.right.right = Node(6)
    root.left.left = Node(1)
    root.left.right = Node(8)
    root.left.right.left = Node(3)
    root.left.right.right = Node(4)

    res = emptyTree(root)

    for x in res:
        print(x, end=" ")
C#
using System;
using System.Collections.Generic;

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

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

class GFG
{

    // Returns the height of the current node
    // and groups nodes having the same height.
    static int getHeight(Node root, Dictionary<int, List<int>> mp)
    {

        if (root == null)
            return 0;

        // Height of left subtree
        int lh = getHeight(root.left, mp);

        // Height of right subtree
        int rh = getHeight(root.right, mp);

        // Height of current node
        int ht = 1 + Math.Max(lh, rh);

        // Store current node at its height level
        if (!mp.ContainsKey(ht))
            mp[ht] = new List<int>();

        mp[ht].Add(root.data);

        return ht;
    }

    static List<int> emptyTree(Node root)
    {

        // Stores the number of nodes removed
        // in each iteration
        List<int> res = new List<int>();

        // Maps height -> nodes at that height
        Dictionary<int, List<int>> mp = new Dictionary<int, List<int>>();

        // Group nodes by height
        getHeight(root, mp);

        // Nodes with the same height are removed
        // in the same iteration
        foreach (var it in mp)
        {
            res.Add(it.Value.Count);
        }

        return res;
    }

    static void Main()
    {

        // Tree structure:
        //          2
        //        /   \
        //       5     7
        //      / \     \
        //     1   8     6
        //        / \
        //       3   4

        Node root = new Node(2);
        root.left = new Node(5);
        root.right = new Node(7);
        root.right.right = new Node(6);
        root.left.left = new Node(1);
        root.left.right = new Node(8);
        root.left.right.left = new Node(3);
        root.left.right.right = new Node(4);

        List<int> res = emptyTree(root);

        foreach (int x in res)
        {
            Console.Write(x + " ");
        }
    }
}
JavaScript
class Node {
    constructor(val) {
        this.data = val;
        this.left = null;
        this.right = null;
    }
}

// Returns the height of the current node
// and groups nodes having the same height.
function getHeight(root, mp) {

    if (root === null)
        return 0;

    // Height of left subtree
    let lh = getHeight(root.left, mp);

    // Height of right subtree
    let rh = getHeight(root.right, mp);

    // Height of current node
    let ht = 1 + Math.max(lh, rh);

    // Store current node at its height level
    if (!mp.has(ht)) mp.set(ht, []);
    mp.get(ht).push(root.data);

    return ht;
}

function emptyTree(root) {

    // Stores the number of nodes removed
    // in each iteration
    let res = [];

    // Maps height -> nodes at that height
    let mp = new Map();

    // Group nodes by height
    getHeight(root, mp);

    // Nodes with the same height are removed
    // in the same iteration
    for (let [key, value] of [...mp.entries()].sort((a,b)=>a[0]-b[0])) {
        res.push(value.length);
    }

    return res;
}

// Driver code

// Tree structure:
//          2
//        /   \
//       5     7
//      / \     \
//     1   8     6
//        / \
//       3   4

let root = new Node(2);
root.left = new Node(5);
root.right = new Node(7);
root.right.right = new Node(6);
root.left.left = new Node(1);
root.left.right = new Node(8);
root.left.right.left = new Node(3);
root.left.right.right = new Node(4);

let res = emptyTree(root);

console.log(res.join(" "));

Output
4 2 1 1 
Comment