Skip to main content

Check Completeness of a Binary Tree

LeetCode 998 | Difficulty: Medium​

Medium

Problem Description​

Given the root of a binary tree, determine if it is a complete binary tree.

In a complete binary tree, every level, except possibly the last, is completely filled, and all nodes in the last level are as far left as possible. It can have between 1 and 2^h nodes inclusive at the last level h.

Example 1:

Input: root = [1,2,3,4,5,6]
Output: true
Explanation: Every level before the last is full (ie. levels with node-values {1} and {2, 3}), and all nodes in the last level ({4, 5, 6}) are as far left as possible.

Example 2:

Input: root = [1,2,3,4,5,null,7]
Output: false
Explanation: The node with value 7 isn't as far left as possible.

Constraints:

- The number of nodes in the tree is in the range `[1, 100]`.

- `1 <= Node.val <= 1000`

Topics: Tree, Breadth-First Search, Binary Tree


Approach​

Tree BFS (Level-Order)​

Use a queue to process the tree level by level. At each level, process all nodes in the queue, then add their children. Track the level size to know when one level ends and the next begins.

When to use

Level-order traversal, level-based aggregation, right/left side view.


Solutions​

Solution 1: C# (Best: 135 ms)​

MetricValue
Runtime135 ms
Memory38.1 MB
Date2022-01-14
Solution
/**
* Definition for a binary tree node.
* public class TreeNode {
* public int val;
* public TreeNode left;
* public TreeNode right;
* public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
public class Solution {
public bool IsCompleteTree(TreeNode root) {
int total = CountNodes(root);
return helper(root, 1, total);
}

private int CountNodes(TreeNode root)
{
if(root == null)
{
return 0;
}
return 1 + CountNodes(root.left) + CountNodes(root.right);
}

private bool helper(TreeNode root, int index, int total)
{
if(root == null) return true;
if(index > total)
{
return false;
}
return helper(root.left, index*2, total) && helper(root.right, index*2+1, total);
}

}
πŸ“œ 3 more C# submission(s)

Submission (2022-01-14) β€” 188 ms, 38.2 MB​

/**
* Definition for a binary tree node.
* public class TreeNode {
* public int val;
* public TreeNode left;
* public TreeNode right;
* public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
public class Solution {
public bool IsCompleteTree(TreeNode root) {
Queue<TreeNode> q = new Queue<TreeNode>();
q.Enqueue(root);
while(q.Peek() != null)
{
var current = q.Dequeue();
q.Enqueue(current.left);
q.Enqueue(current.right);
}
while(q.Count != 0 && q.Peek() == null)
q.Dequeue();

return q.Count == 0;
}
}

Submission (2022-01-14) β€” 221 ms, 38.3 MB​

/**
* Definition for a binary tree node.
* public class TreeNode {
* public int val;
* public TreeNode left;
* public TreeNode right;
* public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
public class Solution {
public bool IsCompleteTree(TreeNode root) {
Queue<TreeNode> q = new Queue<TreeNode>();
q.Enqueue(root);
while(true)
{
var current = q.Dequeue();
if(current.left == null)
{
if(current.right != null) return false;
break;
}
q.Enqueue(current.left);
if(current.right == null) break;
q.Enqueue(current.right);
}
while(q.Count != 0)
{
var current = q.Dequeue();
if(current.left != null || current.right != null)
{
return false;
}
}


return true;
}
}

Submission (2022-01-14) β€” 230 ms, 38 MB​

/**
* Definition for a binary tree node.
* public class TreeNode {
* public int val;
* public TreeNode left;
* public TreeNode right;
* public TreeNode(int val=0, TreeNode left=null, TreeNode right=null) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
public class Solution {
public bool IsCompleteTree(TreeNode root) {
Queue<TreeNode> q = new Queue<TreeNode>();
q.Enqueue(root);
while(q.Peek() != null)
{
var current = q.Dequeue();
if(current.left == null)
{
if(current.right != null) return false;
break;
}
q.Enqueue(current.left);
if(current.right == null) break;
q.Enqueue(current.right);
}
while(q.Count != 0)
{
var current = q.Dequeue();
if(current.left != null || current.right != null)
{
return false;
}
}


return true;
}
}

Complexity Analysis​

ApproachTimeSpace
Tree Traversal$O(n)$$O(h)$

Interview Tips​

Key Points
  • Discuss the brute force approach first, then optimize. Explain your thought process.
  • Consider: "What information do I need from each subtree?" β€” this defines your recursive return value.