Check if all leaves are at same level

Last Updated : 18 Jul, 2026

Given a binary tree with n nodes, determine whether all the leaf nodes are at the same level or not. Return true if all leaf nodes are at the same level, and false otherwise.

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

The idea is to check whether all leaf nodes lie at the same level by comparing the maximum and minimum depth of the binary tree. The maximum depth represents the longest path from the root to any leaf node, while the minimum depth represents the shortest path to a leaf node. If both depths are equal, it means all leaf nodes are present at the same level; otherwise, they are at different levels.

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


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

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

// Function to find maximum depth (height) of the tree
int maxDist(Node* curr) {
    // Base case: if node is NULL, height is 0
    if (curr == NULL) return 0;

    // Recursively find height of left and right subtree
    return 1 + max(maxDist(curr->left), maxDist(curr->right));
}

// Function to find minimum depth of the tree
int minDist(Node* curr) {

    if (curr == NULL) return INT_MAX;

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

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

// Function to check if all leaf nodes are at same level
bool check(Node *root) {

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

    // If both are equal, all leaves are at same level
    if (max_dist == min_dist)
        return true;

    return false;
}

// Driver Code
int main() {
    // Constructing the tree:
    //        10
    //       /  \
    //     20    30
    //    /  \
    //  10   15

    Node* root = new Node(10);
    root->left = new Node(20);
    root->right = new Node(30);
    root->left->left = new Node(10);
    root->left->right = new Node(15);

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

    return 0;
}
C
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

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

// Function to create a new node
struct Node* newNode(int item) {
    struct Node *temp = (struct Node *)malloc(sizeof(struct Node));
    temp->data = item;
    temp->left = temp->right = NULL;
    return temp;
}

// Function to find maximum depth (height) of the tree
int maxDist(struct Node* curr) {
    if (curr == NULL) return 0;
    return 1 + (maxDist(curr->left) > maxDist(curr->right)? maxDist(curr->left) : maxDist(curr->right));
}

// Function to find minimum depth of the tree
int minDist(struct Node* curr) {
    if (curr == NULL) return INT_MAX;
    if (curr->left == NULL && curr->right == NULL) return 1;
    return 1 + (minDist(curr->left) < minDist(curr->right)? minDist(curr->left) : minDist(curr->right));
}

// Function to check if all leaf nodes are at same level
int check(struct Node *root) {
    int max_dist = maxDist(root);
    int min_dist = minDist(root);
    if (max_dist == min_dist) return 1;
    return 0;
}

int main() {
    struct Node *root = newNode(10);
    root->left = newNode(20);
    root->right = newNode(30);
    root->left->left = newNode(10);
    root->left->right = newNode(15);
    if (check(root)) printf("true\n");
    else printf("false\n");
    return 0;
}
Java
class Node {
    int data;
    Node left, right;

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

public class GFG {
    // Function to find maximum depth (height) of the tree
    static int maxDist(Node curr) {
        if (curr == null) return 0;
        return 1 + Math.max(maxDist(curr.left), maxDist(curr.right));
    }

    // Function to find minimum depth of the tree
    static int minDist(Node curr) {
        if (curr == null) return Integer.MAX_VALUE;
        if (curr.left == null && curr.right == null) return 1;
        return 1 + Math.min(minDist(curr.left), minDist(curr.right));
    }

    // Function to check if all leaf nodes are at same level
    static boolean check(Node root) {
        int max_dist = maxDist(root);
        int min_dist = minDist(root);
        return max_dist == min_dist;
    }

    public static void main(String[] args) {
        Node root = new Node(10);
        root.left = new Node(20);
        root.right = new Node(30);
        root.left.left = new Node(10);
        root.left.right = new Node(15);
        if (check(root)) System.out.println("true");
        else System.out.println("false");
    }
}
Python
class Node:
    def __init__(self, item):
        self.data = item
        self.left = None
        self.right = None

# Function to find maximum depth (height) of the tree
def maxDist(curr):
    if curr is None:
        return 0
    return 1 + max(maxDist(curr.left), maxDist(curr.right))

# Function to find minimum depth of the tree
def minDist(curr):
    if curr is None:
        return float('inf')
    if curr.left is None and curr.right is None:
        return 1
    return 1 + min(minDist(curr.left), minDist(curr.right))

# Function to check if all leaf nodes are at same level
def check(root):
    max_dist = maxDist(root)
    min_dist = minDist(root)
    return max_dist == min_dist

# Driver Code
root = Node(10)
root.left = Node(20)
root.right = Node(30)
root.left.left = Node(10)
root.left.right = Node(15)

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

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

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

public class GFG {
    // Function to find maximum depth (height) of the tree
    public static int maxDist(Node curr)
    {
        // Base case: if node is NULL, height is 0
        if (curr == null)
            return 0;

        // Recursively find height of left and right subtree
        return 1
            + Math.Max(maxDist(curr.left),
                       maxDist(curr.right));
    }

    // Function to find minimum depth of the tree
    public static int minDist(Node curr)
    {
        if (curr == null)
            return Int32.MaxValue;

        // If it is a leaf node, minimum depth is 1
        if (curr.left == null && curr.right == null)
            return 1;

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

    // Function to check if all leaf nodes are at same level
    public static bool check(Node root)
    {
        int max_dist = maxDist(root);
        int min_dist = minDist(root);

        // If both are equal, all leaves are at same level
        if (max_dist == min_dist)
            return true;

        return false;
    }

    // Driver Code
    public static void Main()
    {
        // Constructing the tree:
        //        10
        //       /  \
        //     20    30
        //    /  \
        //  10   15

        Node root = new Node(10);
        root.left = new Node(20);
        root.right = new Node(30);
        root.left.left = new Node(10);
        root.left.right = new Node(15);

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

// Function to find maximum depth (height) of the tree
function maxDist(curr) {
    if (curr === null) return 0;
    return 1 + Math.max(maxDist(curr.left), maxDist(curr.right));
}

// Function to find minimum depth of the tree
function minDist(curr) {
    if (curr === null) return Number.MAX_SAFE_INTEGER;
    if (curr.left === null && curr.right === null) return 1;
    return 1 + Math.min(minDist(curr.left), minDist(curr.right));
}

// Function to check if all leaf nodes are at same level
function check(root) {
    const max_dist = maxDist(root);
    const min_dist = minDist(root);
    return max_dist === min_dist;
}

// Driver Code
const root = new Node(10);
root.left = new Node(20);
root.right = new Node(30);
root.left.left = new Node(10);
root.left.right = new Node(15);

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

Output
false

[Expected Approach-1] Single Traversal using Leaf Level Tracking (DFS) - O(n) Time O(h) Space

The idea is to traverse the tree once using DFS and track the level of the first encountered leaf node. For every other leaf node, compare its level with this stored level. If all leaf nodes appear at the same level, return true; otherwise, return false.

Working of Approach:

  • Start DFS traversal from the root with level = 0
  • Store the level of the first encountered leaf in leafLevel
  • For every leaf node, compare its level with leafLevel
  • If any leaf has a different level, return false
  • Recursively check left and right subtrees
  • If all leaf levels match, return true
C++
#include <iostream>
using namespace std;

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

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

// Utility function to check leaf levels
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);
    }

    // Recur 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);
}

// Driver Code
int main()
{
    // Constructing the tree:
    //        10
    //       /  \
    //     20    30
    //    /  \
    //  10   15

    Node *root = new Node(10);
    root->left = new Node(20);
    root->right = new Node(30);
    root->left->left = new Node(10);
    root->left->right = new Node(15);

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

    return 0;
}
C
#include <stdio.h>
#include <stdlib.h>

// Node structure
typedef struct Node {
    int data;
    struct Node *left, *right;
} Node;

// Function to create a new node
Node* newNode(int item) {
    Node* node = (Node*)malloc(sizeof(Node));
    node->data = item;
    node->left = node->right = NULL;
    return node;
}

// Utility function to check leaf levels
int checkUtil(Node *root, int level, int *leafLevel) {
    // If node is null, it does not affect result
    if (root == NULL)
        return 1;

    // 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 1;
        }
        // Compare current leaf level with stored level
        return (level == *leafLevel);
    }

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

int check(Node *root) {
    // Stores level of first encountered leaf
    int leafLevel = 0;
    return checkUtil(root, 0, &leafLevel);
}

int main() {
    // Constructing the tree:
    //        10
    //       /  \
    //     20    30
    //    /  \
    //  10   15

    Node *root = newNode(10);
    root->left = newNode(20);
    root->right = newNode(30);
    root->left->left = newNode(10);
    root->left->right = newNode(15);

    if (check(root))
        printf("true\n");
    else
        printf("false\n");
    return 0;
}
Java
class Node {
    int data;
    Node left, right;

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

public class GFG {
    // Utility function to check leaf levels
    static boolean 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] == 0) {
                leafLevel[0] = level;
                return true;
            }

            // Compare current leaf level with stored level
            return (level == leafLevel[0]);
        }

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

    static boolean check(Node root) {
        // Stores level of first encountered leaf
        int[] leafLevel = {0};
        return checkUtil(root, 0, leafLevel);
    }

    public static void main(String[] args) {
        // Constructing the tree:
        //        10
        //       /  \
        //     20    30
        //    /  \
        //  10   15

        Node root = new Node(10);
        root.left = new Node(20);
        root.right = new Node(30);
        root.left.left = new Node(10);
        root.left.right = new Node(15);

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

# Utility function to check leaf levels
def checkUtil(root, level, leafLevel):
    # If node is null, it does not affect result
    if root is None:
        return True

    # If leaf node, set or compare its level
    if root.left is None and root.right is None:
        # First leaf encountered, store its level
        if leafLevel[0] == 0:
            leafLevel[0] = level
            return True

        # Compare current leaf level with stored level
        return level == leafLevel[0]

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

def check(root):
    # Stores level of first encountered leaf
    leafLevel = [0]
    return checkUtil(root, 0, leafLevel)

# Driver Code
if __name__ == '__main__':
    # Constructing the tree:
    #        10
    #       /  \
    #     20    30
    #    /  \
    #  10   15

    root = Node(10)
    root.left = Node(20)
    root.right = Node(30)
    root.left.left = Node(10)
    root.left.right = Node(15)

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

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

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

class GFG {
    // Utility function to check leaf levels
    static bool CheckUtil(Node root, int level,
                          ref 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;
        }

        // Recur for left and right subtree
        return CheckUtil(root.left, level + 1,
                         ref leafLevel)
            && CheckUtil(root.right, level + 1,
                         ref leafLevel);
    }

    static bool check(Node root)
    {
        // Stores level of first encountered leaf
        int leafLevel = 0;
        return CheckUtil(root, 0, ref leafLevel);
    }

    static void Main()
    {
        // Constructing the tree:
        //        10
        //       /  \
        //     20    30
        //    /  \
        //  10   15

        Node root = new Node(10);
        root.left = new Node(20);
        root.right = new Node(30);
        root.left.left = new Node(10);
        root.left.right = new Node(15);

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

// Utility function to check leaf levels
function checkUtil(root, level, 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] === 0) {
            leafLevel[0] = level;
            return true;
        }

        // Compare current leaf level with stored level
        return level === leafLevel[0];
    }

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

function check(root) {
    // Stores level of first encountered leaf
    let leafLevel = [0];
    return checkUtil(root, 0, leafLevel);
}

// Driver Code
// Constructing the tree:
//        10
//       /  \
//     20    30
//    /  \
//  10   15

let root = new Node(10);
root.left = new Node(20);
root.right = new Node(30);
root.left.left = new Node(10);
root.left.right = new Node(15);

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

Output
false

[Expected Approach-2] Level Order Traversal (BFS) - O(n) Time and O(n) Space

The idea is to use level order traversal (BFS) to check whether all leaf nodes are at the same level. While traversing the tree level by level, we mark when the first leaf node is found. If after that level there are still nodes left to process, it means some leaf nodes exist at a deeper level, so all leaves are not at the same level.

Working of Approach:

  • Start level order traversal using a queue
  • Traverse the tree level by level and push children into the queue
  • If a leaf node is found, mark a flag
  • After each level, check if the flag is set and nodes still remain
  • If yes, return false
  • If traversal completes without issues, return true
C++
#include <iostream>
#include <queue>
using namespace std;

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

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

/*You are required to complete this method*/
bool check(Node *root)
{

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

    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 false;
    }

    return true;
}

// Driver Code
int main() {
    // Constructing the tree:
    //        10
    //       /  \
    //     20    30
    //    /  \
    //  10   15

    Node* root = new Node(10);
    root->left = new Node(20);
    root->right = new Node(30);
    root->left->left = new Node(10);
    root->left->right = new Node(15);

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

    return 0;
}
C
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>

// Define the Node structure
typedef struct Node {
    int data;
    struct Node *left, *right;
} Node;

// Function to create a new Node
Node* newNode(int item) {
    Node *temp = (Node *)malloc(sizeof(Node));
    temp->data = item;
    temp->left = temp->right = NULL;
    return temp;
}

// Function to check if the tree is a complete binary tree
bool check(Node *root) {
    // If tree is empty, return true
    if (!root)
        return true;
    
    Node *queue[1000];
    int front = 0, rear = 0;
    queue[rear++] = root;
    
    int flag = 0;
    
    // Level order traversal
    while (front < rear) {
        int n = rear - front;
        
        for (int i = 0; i < n; i++) {
            Node *temp = queue[front++];
            
            // Push left and right children
            if (temp->left)
                queue[rear++] = temp->left;
            if (temp->right)
                queue[rear++] = 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 && rear > front)
            return false;
    }
    
    return true;
}

// Driver Code
int main() {
    // Constructing the tree:
    //        10
    //       /  \
    //     20    30
    //    /  \
    //  10   15
    
    Node* root = newNode(10);
    root->left = newNode(20);
    root->right = newNode(30);
    root->left->left = newNode(10);
    root->left->right = newNode(15);
    
    // Calling check function
    if (check(root))
        printf("true\n");
    else
        printf("false\n");
    
    return 0;
}
Java
import java.util.*;

// Define the Node class
class Node {
    int data;
    Node left, right;

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

public class GFG {
    // Function to check if the tree is a complete binary tree
    static boolean check(Node root) {
        // If tree is empty, return true
        if (root == null)
            return true;
        
        Queue<Node> q = new LinkedList<>();
        q.add(root);
        
        int flag = 0;
        
        // Level order traversal
        while (!q.isEmpty()) {
            int n = q.size();
            
            for (int i = 0; i < n; i++) {
                Node temp = q.poll();
                
                // Push left and right children
                if (temp.left!= null)
                    q.add(temp.left);
                if (temp.right!= null)
                    q.add(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!= 0 &&!q.isEmpty())
                return false;
        }
        
        return true;
    }
    
    // Driver Code
    public static void main(String[] args) {
        // Constructing the tree:
        //        10
        //       /  \
        //     20    30
        //    /  \
        //  10   15
        
        Node root = new Node(10);
        root.left = new Node(20);
        root.right = new Node(30);
        root.left.left = new Node(10);
        root.left.right = new Node(15);
        
        // Calling check function
        if (check(root))
            System.out.println("true");
        else
            System.out.println("false");
    }
}
Python
from collections import deque

# Define the Node class
class Node:
    def __init__(self, item):
        self.data = item
        self.left = None
        self.right = None

# Function to check if the tree is a complete binary tree
def check(root):
    # If tree is empty, return true
    if not root:
        return True
    
    queue = deque([root])
    
    flag = 0
    
    # Level order traversal
    while queue:
        n = len(queue)
        
        for _ in range(n):
            temp = queue.popleft()
            
            # Push left and right children
            if temp.left:
                queue.append(temp.left)
            if temp.right:
                queue.append(temp.right)
            
            # If leaf node found, mark flag
            if not temp.left and not temp.right:
                flag = 1
        
        # If leaf found and more nodes exist at next level
        if flag and queue:
            return False
    
    return True

# Driver Code
if __name__ == '__main__':
    # Constructing the tree:
    #        10
    #       /  \
    #     20    30
    #    /  \
    #  10   15
    
    root = Node(10)
    root.left = Node(20)
    root.right = Node(30)
    root.left.left = Node(10)
    root.left.right = Node(15)
    
    # Calling check function
    if check(root):
        print('true')
    else:
        print('false')
C#
using System;
using System.Collections.Generic;

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

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

public class GFG
{
  /*You are required to complete this method*/
  public static bool check(Node root)
  {
      // If tree is empty, return true
      if (root == null)
          return true;

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

      int flag = 0;

      // Level order traversal
      while (q.Count > 0)
      {
          int n = q.Count;

          for (int i = 0; i < n; i++)
          {
              Node temp = q.Dequeue();

              // Push left and right children
              if (temp.left!= null)
                  q.Enqueue(temp.left);
              if (temp.right!= null)
                  q.Enqueue(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 > 0 && q.Count > 0)
              return false;
      }

      return true;
  }

  // Driver Code
  public static void Main(string[] args)
  {
      // Constructing the tree:
      //        10
      //       /  \
      //     20    30
      //    /  \
      //  10   15

      Node root = new Node(10);
      root.left = new Node(20);
      root.right = new Node(30);
      root.left.left = new Node(10);
      root.left.right = new Node(15);

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

/*You are required to complete this method*/
function check(root) {

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

  let q = [];
  q.push(root);

  let flag = 0;

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

    let n = q.length;

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

      let temp = q.shift();

      // 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.length > 0)
      return false;
  }

  return true;
}

// Driver Code
// Constructing the tree:
//        10
//       /  \
//     20    30
//    /  \
//  10   15

let root = new Node(10);
root.left = new Node(20);
root.right = new Node(30);
root.left.left = new Node(10);
root.left.right = new Node(15);

// Calling check function
if (check(root))
  console.log('true');
else
  console.log('false');

Output
false
Comment