Given a Binary Tree, check if all leaves are at same level or not.
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
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.
#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;
}
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");
}
}
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")
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");
}
}
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
#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;
}
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");
}
}
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")
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");
}
}
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.
#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;
}
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");
}
}
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")
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");
}
}
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


