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 2h
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:
[1, 100]
.1 <= Node.val <= 1000
This problem asks to determine if a given binary tree is a complete binary tree. A complete binary tree is a binary tree in which every level, except possibly the last, is completely filled, and all nodes in the last level are as far left as possible.
The most efficient approach to solve this problem is using Breadth-First Search (BFS). BFS visits nodes level by level. We leverage this property to check for the completeness criteria.
Algorithm:
q
and initialize it with the root node.null
, it means we've encountered a missing node and should proceed to check the remaining queue elements.null
):
Time Complexity Analysis:
The BFS traversal visits each node in the tree exactly once. Therefore, the time complexity is O(N), where N is the number of nodes in the tree.
Space Complexity Analysis:
The space complexity is O(W), where W is the maximum width of the binary tree. In the worst-case scenario (a complete binary tree), W can be proportional to N (number of nodes), resulting in O(N) space complexity. In a balanced tree, W is log₂(N).
from collections import deque
# Definition for a binary tree node.
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution:
def isCompleteTree(self, root: TreeNode) -> bool:
q = deque([root])
while q:
node = q.popleft()
if node is None:
break #Encountered a missing node
q.append(node.left)
q.append(node.right)
return all(node is None for node in q) #Check if all remaining are None
The Python code directly implements the algorithm described above. It uses collections.deque
for efficient queue operations. The all(node is None for node in q)
check elegantly verifies the completeness condition after the BFS.
import java.util.*;
class Solution {
public boolean isCompleteTree(TreeNode root) {
Deque<TreeNode> q = new LinkedList<>();
q.offer(root);
while (q.peek() != null) {
TreeNode node = q.poll();
q.offer(node.left);
q.offer(node.right);
}
while (!q.isEmpty() && q.peek() == null) {
q.poll();
}
return q.isEmpty();
}
}
The Java code mirrors the Python solution's logic. LinkedList
is used as a deque, offering efficient offer
(enqueue) and poll
(dequeue) operations. The loop continues until the first null node is encountered. The second loop removes trailing nulls, and finally, q.isEmpty()
determines completeness.
The C++, and Go solutions follow the same algorithmic approach with appropriate data structure usage for their respective languages. The core logic remains consistent across all provided implementations.