Description
給定一棵二元樹的根節點,判斷它是否為完全二元樹。完全二元樹除了最後一層外,每層都完全填滿,且最後一層的節點盡量靠左。
Example:
Input: root = [1,2,3,4,5,6] Output: true
Intuition#
BFS 遍歷時,遇到 null 後不應該再出現非 null 節點。
- 完全二元樹的特性:在層序遍歷中,所有非 null 節點必須連續出現
- 一旦遇到第一個 null,之後所有節點都必須是 null
- 用 BFS 逐層掃描,設定一個旗標記錄是否已遇到 null
Approaches#
1: BFS + 旗標#
- 概念: 層序遍歷,遇到 null 設旗標,之後若再遇到非 null 節點就不是完全二元樹
- 時間複雜度:
O(n) - 空間複雜度:
O(n)
class Solution {
fun isCompleteTree(root: TreeNode?): Boolean {
if (root == null) return true
val queue: Queue<TreeNode?> = LinkedList()
queue.offer(root)
var seenNull = false
while (queue.isNotEmpty()) {
val node = queue.poll()
if (node == null) {
seenNull = true
} else {
if (seenNull) return false
queue.offer(node.left)
queue.offer(node.right)
}
}
return true
}
}⭐ 2: BFS + 索引檢查#
- 概念: 為每個節點編號(根為 1,左子 2i,右子 2i+1),若樹是完全的,最大編號應等於節點總數
- 時間複雜度:
O(n) - 空間複雜度:
O(n)
class Solution {
fun isCompleteTree(root: TreeNode?): Boolean {
if (root == null) return true
val queue: Queue<Pair<TreeNode, Int>> = LinkedList()
queue.offer(root to 1)
var count = 0
var maxIndex = 0
while (queue.isNotEmpty()) {
val (node, index) = queue.poll()
count++
maxIndex = maxOf(maxIndex, index)
node.left?.let { queue.offer(it to index * 2) }
node.right?.let { queue.offer(it to index * 2 + 1) }
}
return maxIndex == count
}
}🔑 Takeaways#
- Pattern: 完全二元樹的判定可以透過 BFS 層序遍歷檢查 null 的連續性
- 關鍵技巧: 「遇到 null 後不能再有非 null」是最直覺的判定方式;索引法則提供了另一種數學角度的驗證