今天是學習的第 22 天,主要學習了 BFS 的適用場景:
這邊以 LeetCode 第 111 題「二叉樹的最小深度」為例:
最小深度是從根節點到最近葉子節點(沒有子節點的節點)的最短路徑上的節點數量。
二叉樹的最小深度指的是「根節點到最近的葉節點的距離」,這邊先以 DFS 為例:
var minDepth = function(root) {
if (root === null) {
return 0;
}
// 記錄最小深度(根結點到最近的葉子節點的距離)
let minDepthValue = Infinity;
// 記錄當前遍歷到的節點深度
let currentDepth = 0;
const traverse = function(root) {
if (root === null) {
return;
}
// 前序位置進入節點時增加當前深度
currentDepth++;
// 如果當前節點是葉子節點,更新最小深度
if (root.left === null && root.right === null) {
minDepthValue = Math.min(minDepthValue, currentDepth);
}
traverse(root.left);
traverse(root.right);
// 後續位置離開節點時減少當前深度
currentDepth--;
};
// 從根結點開始 DFS 遍歷
traverse(root);
return minDepthValue;
};
但 DFS 的寫法有個缺點:必須遍歷整棵樹才能找到最小深度,因為需要比較所有從根節點到葉子節點的路徑長度。
因此這裡可以利用 BFS 層序遍歷的特性,一旦遇到第一個葉子節點就能得到最小深度:
var minDepth = function(root) {
if (root === null) return 0;
let q = [root];
// root 本身就是一層,depth 初始化為 1
let depth = 1;
while (q.length > 0) {
let sz = q.length;
// 遍歷當前層數的節點
for (let i = 0; i < sz; i++) {
let cur = q.shift();
// 判斷是否到達葉子節點
if (cur.left === null && cur.right === null)
return depth;
// 將下一層加入隊列
if (cur.left !== null)
q.push(cur.left);
if (cur.right !== null)
q.push(cur.right);
}
// 這裡增加深度
depth++;
}
return depth;
};
由於 BFS 層序遍歷的特性,演算法可能不需要遍歷完所有節點就能提前結束。