class TreeNode {
char val;
TreeNode left;
TreeNode right;
TreeNode(char val) { this.val = val; }
}
深度定義:根節點到最遠葉節點的最長路徑上的節點數。空樹深度 0。
public class BinaryTreeMetrics {
/** 遞迴計算最大深度 */
public static int maxDepth(TreeNode root) {
if (root == null) return 0;
int leftDepth = maxDepth(root.left);
int rightDepth = maxDepth(root.right);
return 1 + Math.max(leftDepth, rightDepth);
}
/** 迭代版(層序遍歷計數層數) */
public static int maxDepthIterative(TreeNode root) {
if (root == null) return 0;
Queue queue = new LinkedList<>();
queue.offer(root);
int depth = 0;
while (!queue.isEmpty()) {
int levelSize = queue.size();
for (int i = 0; i < levelSize; i++) {
TreeNode node = queue.poll();
if (node.left != null) queue.offer(node.left);
if (node.right != null) queue.offer(node.right);
}
depth++;
}
return depth;
}
}
寬度定義:同一層級節點數的最大值。利用佇列逐層遍歷,每層遍歷前記錄佇列大小即為該層寬度。
import java.util.*;
public class BinaryTreeMetrics {
/** 計算最大寬度 */
public static int maxWidth(TreeNode root) {
if (root == null) return 0;
Queue queue = new ArrayDeque<>();
queue.offer(root);
int maxWidth = 1; // 至少根節點一層寬度為 1
while (!queue.isEmpty()) {
int levelSize = queue.size(); // 當前層節點數
maxWidth = Math.max(maxWidth, levelSize);
// 遍歷當前層,將下一層節點入隊
for (int i = 0; i < levelSize; i++) {
TreeNode node = queue.poll();
if (node.left != null) queue.offer(node.left);
if (node.right != null) queue.offer(node.right);
}
}
return maxWidth;
}
/** 進階:計算每層寬度詳情(含 null 佔位的完全二叉樹寬度) */
public static int maxWidthWithNullPlaceholders(TreeNode root) {
if (root == null) return 0;
// 隊列存儲 (節點, 編號),根編號 1,左 2*i,右 2*i+1
Queue> queue = new LinkedList<>();
queue.offer(new Pair<>(root, 1L));
long maxWidth = 0;
while (!queue.isEmpty()) {
int levelSize = queue.size();
long firstIdx = queue.peek().getValue();
long lastIdx = firstIdx;
for (int i = 0; i < levelSize; i++) {
Pair pair = queue.poll();
lastIdx = pair.getValue();
TreeNode node = pair.getKey();
if (node.left != null) queue.offer(new Pair<>(node.left, lastIdx * 2));
if (node.right != null) queue.offer(new Pair<>(node.right, lastIdx * 2 + 1));
}
maxWidth = Math.max(maxWidth, lastIdx - firstIdx + 1);
}
return (int) maxWidth;
}
// 簡易 Pair 類
static class Pair {
private final K key; private final V value;
Pair(K k, V v) { key = k; value = v; }
K getKey() { return key; } V getValue() { return value; }
}
}
public class TreeMetricsTest {
public static void main(String[] args) {
// 建構測試樹:
// A(1)
// / \
// B C(2)
// / / \
// D E F(3)
// / / \
// G H I(4)
TreeNode root = new TreeNode('A');
root.left = new TreeNode('B');
root.right = new TreeNode('C');
root.left.left = new TreeNode('D');
root.right.left = new TreeNode('E');
root.right.right = new TreeNode('F');
root.left.left.left = new TreeNode('G');
root.right.right.left = new TreeNode('H');
root.right.right.right = new TreeNode('I');
System.out.println("最大深度(遞迴): " + BinaryTreeMetrics.maxDepth(root)); // 4
System.out.println("最大深度(迭代): " + BinaryTreeMetrics.maxDepthIterative(root)); // 4
System.out.println("最大寬度(節點數): " + BinaryTreeMetrics.maxWidth(root)); // 3 (第3層: D,E,F)
System.out.println("最大寬度(含null位置): " + BinaryTreeMetrics.maxWidthWithNullPlaceholders(root)); // 4 (第4層: G,null,H,I)
}
}
| 算法 | 時間複雜度 | 空間複雜度 | 備註 |
|---|---|---|---|
| 遞迴深度 | O(n) | O(h) | h=樹高,最壞 O(n) 棧溢位風險 |
| 迭代深度 | O(n) | O(w) | w=最大寬度,最壞 O(n/2) |
| 最大寬度 | O(n) | O(w) | 標準 BFS |
| 含 null 寬度 | O(n) | O(w) | 編號可能溢出 long,深樹需 BigInteger |