Check if all leaves are at same level

Last Updated : 9 Apr, 2026

Given a Binary Tree, check if all leaves are at same level or not. 

Examples:

Input:

1

Output: true

Input:

nodes_at_same_level_2

Output: false

Input:

nodes_at_same_level_3

Output: true

Try It Yourself
redirect icon

[Naive Approach] Recursive with Two Traversals - O(n) Time and O(n) Space

Compute the maximum depth (farthest leaf) and minimum depth (nearest leaf) of the tree. The minimum depth is found recursively by returning 1 for a leaf, ignoring null children (treating them as very large value), and taking min(left, right) + 1 for other nodes. Finally, compare both values. If they are equal, all leaf nodes are at the same level; otherwise, they are not.

C++
#include <iostream>
#include <climits>
using namespace std;

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

    Node(int item) {
        data = item;
        left = right = NULL;
    }
};

int maxDist(Node* curr) {

    // If node is null, contributes 0 to height
    if (curr == NULL) return 0;

    // Return maximum depth from left and right subtree
    return 1 + max(maxDist(curr->left), maxDist(curr->right));
}

int minDist(Node* curr) {

    // Ignore null paths by treating them as very large
    if (curr == NULL) return INT_MAX;

    // If leaf node, distance is 1
    if (curr->left == NULL && curr->right == NULL)
        return 1;

    // Return minimum depth from left and right subtree
    return 1 + min(minDist(curr->left), minDist(curr->right));
}

int main() {
    Node* root = new Node(12);
    root->left = new Node(5);
    root->left->left = new Node(3);
    root->left->right = new Node(9);
    root->left->left->left = new Node(1);
    root->left->right->left = new Node(1);

    int max_dist = maxDist(root);
    int min_dist = minDist(root);

    if (max_dist == min_dist)
        cout << "true\n";
    else
        cout << "false\n";

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

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

public class GFG {

    static int maxDist(Node curr) {

        // If node is null, contributes 0 to height
        if (curr == null) return 0;

        // Return maximum depth from left and right subtree
        return 1 + Math.max(maxDist(curr.left), maxDist(curr.right));
    }

    static int minDist(Node curr) {

        // Ignore null paths by treating them as very large
        if (curr == null) return Integer.MAX_VALUE;

        // If leaf node, distance is 1
        if (curr.left == null && curr.right == null)
            return 1;

        // Return minimum depth from left and right subtree
        return 1 + Math.min(minDist(curr.left), minDist(curr.right));
    }

    public static void main(String[] args) {

        Node root = new Node(12);
        root.left = new Node(5);
        root.left.left = new Node(3);
        root.left.right = new Node(9);
        root.left.left.left = new Node(1);
        root.left.right.left = new Node(1);

        int max_dist = maxDist(root);
        int min_dist = minDist(root);

        if (max_dist == min_dist)
            System.out.println("true");
        else
            System.out.println("false");
    }
}
Python
import sys

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

def maxDist(curr):

    # If node is None, contributes 0 to height
    if curr is None:
        return 0

    # Return maximum depth from left and right subtree
    return 1 + max(maxDist(curr.left), maxDist(curr.right))

def minDist(curr):

    # Ignore null paths by treating them as very large
    if curr is None:
        return sys.maxsize

    # If leaf node, distance is 1
    if curr.left is None and curr.right is None:
        return 1

    # Return minimum depth from left and right subtree
    return 1 + min(minDist(curr.left), minDist(curr.right))

if __name__ == "__main__":
    root = Node(12)
    root.left = Node(5)
    root.left.left = Node(3)
    root.left.right = Node(9)
    root.left.left.left = Node(1)
    root.left.right.left = Node(1)

    max_dist = maxDist(root)
    min_dist = minDist(root)

    if max_dist == min_dist:
        print("true")
    else:
        print("false")
C#
using System;

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

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

class GFG {
    static int maxDist(Node curr) {

        // If node is null, contributes 0 to height
        if (curr == null) return 0;

        // Return maximum depth from left and right subtree
        return 1 + Math.Max(maxDist(curr.left), maxDist(curr.right));
    }

    static int minDist(Node curr) {

        // Ignore null paths by treating them as very large
        if (curr == null) return Int32.MaxValue;

        // If leaf node, distance is 1
        if (curr.left == null && curr.right == null)
            return 1;

        // Return minimum depth from left and right subtree
        return 1 + Math.Min(minDist(curr.left), minDist(curr.right));
    }

    static void Main(string[] args) {
        Node root = new Node(12);
        root.left = new Node(5);
        root.left.left = new Node(3);
        root.left.right = new Node(9);
        root.left.left.left = new Node(1);
        root.left.right.left = new Node(1);

        int max_dist = maxDist(root);
        int min_dist = minDist(root);

        if (max_dist == min_dist)
            Console.WriteLine("true");
        else
            Console.WriteLine("false");
    }
}
JavaScript
class Node {
    constructor(item) {
        this.data = item;
        this.left = null;
        this.right = null;
    }
}

function maxDist(curr) {

    // If node is null, contributes 0 to height
    if (curr === null) return 0;

    // Return maximum depth from left and right subtree
    return 1 + Math.max(maxDist(curr.left), maxDist(curr.right));
}

function minDist(curr) {

    // Ignore null paths by treating them as very large
    if (curr === null) return Number.MAX_SAFE_INTEGER;

    // If leaf node, distance is 1
    if (curr.left === null && curr.right === null)
        return 1;

    // Return minimum depth from left and right subtree
    return 1 + Math.min(minDist(curr.left), minDist(curr.right));
}

// Driver code
const root = new Node(12);
root.left = new Node(5);
root.left.left = new Node(3);
root.left.right = new Node(9);
root.left.left.left = new Node(1);
root.left.right.left = new Node(1);

const max_dist = maxDist(root);
const min_dist = minDist(root);

if (max_dist === min_dist)
    console.log("true");
else
    console.log("false");

Output
true



Output
true

[Expected Approach-1] Recursive with Single Traversal

  • Traverse the tree using Preorder traversal
  • Keep track of current level and a leafLevel (initially unset)
  • If node is NULL, return true
  • If node is a leaf and leafLevel is unset, store current level
  • If node is a leaf and leafLevel is already set, compare levels (return false if mismatch)
  • Recursively check left and right subtree with level + 1
  • Return true only if all leaf nodes have the same level
C++
#include <iostream>
using namespace std;

struct Node {
    int data;
    Node *left, *right;

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

bool checkUtil(Node* root, int level, int* leafLevel) {

    // If node is null, it does not affect result
    if (root == NULL) return true;

    // If leaf node, set or compare its level
    if (root->left == NULL && root->right == NULL) {

        // First leaf encountered, store its level
        if (*leafLevel == 0) {
            *leafLevel = level;
            return true;
        }

        // Compare current leaf level with stored level
        return (level == *leafLevel);
    }

    // Check for left and right subtree
    return checkUtil(root->left, level + 1, leafLevel) &&
           checkUtil(root->right, level + 1, leafLevel);
}

bool check(Node* root) {

    // Stores level of first encountered leaf
    int leafLevel = 0;

    return checkUtil(root, 0, &leafLevel);
}

int main() {
    Node* root = new Node(12);
    root->left = new Node(5);
    root->left->left = new Node(3);
    root->left->right = new Node(9);
    root->left->left->left = new Node(1);
    root->left->right->left = new Node(1);

    if (check(root))
        cout << "true\n";
    else
        cout << "false\n";

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

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

class Leaf {
    int leaflevel = 0;
}

public class GFG {

    Node root;
    Leaf mylevel = new Leaf();

    boolean checkUtil(Node node, int level, Leaf leafLevel) {

        // If node is null, it does not affect result
        if (node == null) return true;

        // If leaf node, set or compare its level
        if (node.left == null && node.right == null) {

            // First leaf encountered, store its level
            if (leafLevel.leaflevel == 0) {
                leafLevel.leaflevel = level;
                return true;
            }

            // Compare current leaf level with stored level
            return (level == leafLevel.leaflevel);
        }

        // Check for left and right subtree
        return checkUtil(node.left, level + 1, leafLevel) &&
               checkUtil(node.right, level + 1, leafLevel);
    }

    boolean check(Node node) {
        return checkUtil(node, 0, mylevel);
    }

    public static void main(String args[]) {
        GFG tree = new GFG();
        tree.root = new Node(12);
        tree.root.left = new Node(5);
        tree.root.left.left = new Node(3);
        tree.root.left.right = new Node(9);
        tree.root.left.left.left = new Node(1);
        tree.root.left.right.left = new Node(1);

        if (tree.check(tree.root))
            System.out.println("true");
        else
            System.out.println("false");
    }
}
Python
class Node:
    def __init__(self, data):
        self.data = data
        self.left = self.right = None

class Leaf:
    def __init__(self):
        self.leaflevel = 0

def checkUtil(node, level, leafLevel):

    # If node is None, it does not affect result
    if node is None:
        return True

    # If leaf node, set or compare its level
    if node.left is None and node.right is None:

        # First leaf encountered, store its level
        if leafLevel.leaflevel == 0:
            leafLevel.leaflevel = level
            return True

        # Compare current leaf level with stored level
        return level == leafLevel.leaflevel

    # Check for left and right subtree
    return (checkUtil(node.left, level + 1, leafLevel) and
            checkUtil(node.right, level + 1, leafLevel))

def check(root):
    mylevel = Leaf()
    return checkUtil(root, 0, mylevel)

if __name__ == "__main__":
    root = Node(12)
    root.left = Node(5)
    root.left.left = Node(3)
    root.left.right = Node(9)
    root.left.left.left = Node(1)
    root.left.right.left = Node(1)

    if check(root):
        print("true")
    else:
        print("false")
C#
using System;

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

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

public class Leaf
{
    public int leaflevel = 0;
}

class GFG
{
    public Node root;
    public Leaf mylevel = new Leaf();

    public bool checkUtil(Node node, int level, Leaf leafLevel)
    {
        if (node == null) return true;

        // If leaf node, set or compare level
        if (node.left == null && node.right == null)
        {
            if (leafLevel.leaflevel == 0)
            {
                leafLevel.leaflevel = level;
                return true;
            }
            return (level == leafLevel.leaflevel);
        }

        // Check for left and right subtree
        return checkUtil(node.left, level + 1, leafLevel) &&
               checkUtil(node.right, level + 1, leafLevel);
    }

    public bool check(Node node)
    {
        return checkUtil(node, 0, mylevel);
    }

    public static void Main(string[] args)
    {
        GFG tree = new GFG();
        tree.root = new Node(12);
        tree.root.left = new Node(5);
        tree.root.left.left = new Node(3);
        tree.root.left.right = new Node(9);
        tree.root.left.left.left = new Node(1);
        tree.root.left.right.left = new Node(1);

        if (tree.check(tree.root))
            Console.WriteLine("true");
        else
            Console.WriteLine("false");
    }
}
JavaScript
class Node {
    constructor(item) {
        this.data = item;
        this.left = this.right = null;
    }
}

class Leaf {
    constructor() {
        this.leaflevel = 0;
    }
}

let mylevel = new Leaf();

function checkUtil(node, level, leafLevel) {

    // If node is null, it does not affect result
    if (node == null) return true;

    // If leaf node, set or compare its level
    if (node.left == null && node.right == null) {

        // First leaf encountered, store its level
        if (leafLevel.leaflevel === 0) {
            leafLevel.leaflevel = level;
            return true;
        }

        // Compare current leaf level with stored level
        return level === leafLevel.leaflevel;
    }

    // Check for left and right subtree
    return checkUtil(node.left, level + 1, leafLevel) &&
           checkUtil(node.right, level + 1, leafLevel);
}

function check(node) {
    mylevel.leaflevel = 0;
    return checkUtil(node, 0, mylevel);
}

// Driver code
let root = new Node(12);
root.left = new Node(5);
root.left.left = new Node(3);
root.left.right = new Node(9);
root.left.left.left = new Node(1);
root.left.right.left = new Node(1);

if (check(root))
    console.log("true");
else
    console.log("false");

Output
true

Time Complexity: The function does a simple traversal of the tree, so the complexity is O(n).
Auxiliary Space: O(H) for call stack, where H is height of tree

[Expected Approach-2] Iterative with Single Traversal - O(n) Time and O(n) Space

Iteratively traverse the tree and when you encounter the first leaf node, store its level in result variable. Whenever you encounter any leaf node, compare its level with previously stored result. If they have the same level then proceed for the rest of tree, else return false.

C++
#include <iostream>
#include <queue>
using namespace std;

struct Node {
    int data;
    Node *left, *right;

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

int checkLevelLeafNode(Node* root) {

    // If tree is empty, return true
    if (!root) return 1;

    queue<Node*> q;
    q.push(root);

    int flag = 0;

    // Level order traversal
    while (!q.empty()) {

        int n = q.size();

        for (int i = 0; i < n; i++) {

            Node* temp = q.front();
            q.pop();

            // Push left and right children
            if (temp->left) q.push(temp->left);
            if (temp->right) q.push(temp->right);

            // If leaf node found, mark flag
            if (temp->left == NULL && temp->right == NULL)
                flag = 1;
        }

        // If leaf found and more nodes exist at next level
        if (flag && !q.empty())
            return 0;
    }

    return 1;
}

int main() {
    Node* root = new Node(1);
    root->left = new Node(2);
    root->right = new Node(3);
    root->left->right = new Node(4);
    root->right->left = new Node(5);
    root->right->right = new Node(6);

    if (checkLevelLeafNode(root))
        cout << "true\n";
    else
        cout << "false\n";

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

class Node {
    int data;
    Node left, right;

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

public class GFG {

    static boolean checkLevelLeafNode(Node root) {

        // If tree is empty, return true
        if (root == null) return true;

        Queue<Node> q = new LinkedList<>();
        q.add(root);

        int level = 0;
        int result = Integer.MAX_VALUE;

        // Level order traversal
        while (!q.isEmpty()) {

            int size = q.size();
            level++;

            while (size-- > 0) {

                Node temp = q.poll();

                // Process left child
                if (temp.left != null) {
                    q.add(temp.left);

                    // If leaf node, set or compare its level
                    if (temp.left.left == null && temp.left.right == null) {

                        // First leaf encountered, store its level
                        if (result == Integer.MAX_VALUE)
                            result = level;

                        // Compare with previously stored level
                        else if (result != level)
                            return false;
                    }
                }

                // Process right child
                if (temp.right != null) {
                    q.add(temp.right);

                    // If leaf node, set or compare its level
                    if (temp.right.left == null && temp.right.right == null) {

                        // First leaf encountered, store its level
                        if (result == Integer.MAX_VALUE)
                            result = level;

                        // Compare with previously stored level
                        else if (result != level)
                            return false;
                    }
                }
            }
        }

        return true;
    }

    public static void main(String[] args) {
        Node root = new Node(1);
        root.left = new Node(2);
        root.right = new Node(3);
        root.left.right = new Node(4);
        root.right.left = new Node(5);
        root.right.right = new Node(6);

        if (checkLevelLeafNode(root))
            System.out.println("true");
        else
            System.out.println("false");
    }
}
Python
class Node:
    def __init__(self, data):
        self.data = data
        self.left = self.right = None

def checkLevelLeafNode(root):

    # If tree is empty, return true
    if not root:
        return True

    q = [root]
    level = 0
    leaf_level = None

    # Level order traversal
    while q:
        size = len(q)
        level += 1

        for _ in range(size):

            temp = q.pop(0)

            # Process left child
            if temp.left:
                q.append(temp.left)

                # If leaf node, set or compare its level
                if not temp.left.left and not temp.left.right:

                    # First leaf encountered, store its level
                    if leaf_level is None:
                        leaf_level = level

                    # Compare with previously stored level
                    elif leaf_level != level:
                        return False

            # Process right child
            if temp.right:
                q.append(temp.right)

                # If leaf node, set or compare its level
                if not temp.right.left and not temp.right.right:

                    # First leaf encountered, store its level
                    if leaf_level is None:
                        leaf_level = level

                    # Compare with previously stored level
                    elif leaf_level != level:
                        return False

    return True

if __name__ == "__main__":
    root = Node(1)
    root.left = Node(2)
    root.right = Node(3)
    root.left.right = Node(4)
    root.right.left = Node(5)
    root.right.right = Node(6)

    if checkLevelLeafNode(root):
        print("true")
    else:
        print("false")
C#
using System;
using System.Collections.Generic;

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

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

public class GFG {
    static bool checkLevelLeafNode(Node root) {
        
        // If tree is empty, return true
        if (root == null) return true;

        Queue<Node> q = new Queue<Node>();
        q.Enqueue(root);

        int level = 0;
        int leafLevel = int.MaxValue;

        // Level order traversal
        while (q.Count != 0) {
            int size = q.Count;
            level++;

            while (size-- > 0) {
                Node temp = q.Dequeue();

                // Process left child
                if (temp.left != null) {
                    q.Enqueue(temp.left);

                    // If leaf node, set or compare its level
                    if (temp.left.left == null && temp.left.right == null) {
                        // First leaf encountered, store its level
                        if (leafLevel == int.MaxValue)
                            leafLevel = level;

                        // Compare with previously stored level
                        else if (leafLevel != level)
                            return false;
                    }
                }

                // Process right child
                if (temp.right != null) {
                    q.Enqueue(temp.right);

                    // If leaf node, set or compare its level
                    if (temp.right.left == null && temp.right.right == null) {
                        // First leaf encountered, store its level
                        if (leafLevel == int.MaxValue)
                            leafLevel = level;

                        // Compare with previously stored level
                        else if (leafLevel != level)
                            return false;
                    }
                }
            }
        }

        return true;
    }

    public static void Main(string[] args) {
        Node root = new Node(1);
        root.left = new Node(2);
        root.right = new Node(3);
        root.left.right = new Node(4);
        root.right.left = new Node(5);
        root.right.right = new Node(6);

        if (checkLevelLeafNode(root))
            Console.WriteLine("true");
        else
            Console.WriteLine("false");
    }
}
JavaScript
class Node {
    constructor(key) {
        this.data = key;
        this.left = this.right = null;
    }
}

function checkLevelLeafNode(root) {

    // If tree is empty, return true
    if (root == null) return true;

    let q = [root];
    let level = 0;
    let leafLevel = Number.MAX_VALUE;

    // Level order traversal
    while (q.length !== 0) {

        let size = q.length;
        level++;

        while (size-- > 0) {

            let temp = q.shift();

            // Process left child
            if (temp.left) {
                q.push(temp.left);

                // If leaf node, set or compare its level
                if (!temp.left.left && !temp.left.right) {

                    // First leaf encountered, store its level
                    if (leafLevel === Number.MAX_VALUE)
                        leafLevel = level;

                    // Compare with previously stored level
                    else if (leafLevel !== level)
                        return false;
                }
            }

            // Process right child
            if (temp.right) {
                q.push(temp.right);

                // If leaf node, set or compare its level
                if (!temp.right.left && !temp.right.right) {

                    // First leaf encountered, store its level
                    if (leafLevel === Number.MAX_VALUE)
                        leafLevel = level;

                    // Compare with previously stored level
                    else if (leafLevel !== level)
                        return false;
                }
            }
        }
    }

    return true;
}

// Driver code
let root = new Node(1);
root.left = new Node(2);
root.right = new Node(3);
root.left.right = new Node(4);
root.right.left = new Node(5);
root.right.right = new Node(6);

if (checkLevelLeafNode(root))
    console.log("true");
else
    console.log("false");

Output
true


Comment