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:
Output: true
Input:
Output: false
Input:
Output: true
Table of Content
[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.
#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;
}
#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;
}
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");
}
}
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')
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");
}
}
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
#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;
}
#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;
}
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");
}
}
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')
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");
}
}
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
#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;
}
#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;
}
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");
}
}
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')
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");
}
}
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


