給定一棵二叉樹和一個目標和 sum,判斷樹中是否存在從根節點到葉子節點的路徑,使得路徑上所有節點值的和等於目標和。
說明:葉子節點是指沒有子節點的節點。
5
/ \
4 8
/ / \
11 13 4
/ \ \
7 2 1
給定 sum = 22,存在路徑 5 → 4 → 11 → 2,和為 22,返回 true。
核心思路:將問題轉化為子問題——從當前節點出發,是否存在路徑和為 sum - node.val。遇到葉子節點時直接判斷剩餘值是否等於節點值。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public boolean hasPathSum(TreeNode root, int sum) {
if (root == null) {
return false;
}
// 到達葉子節點,判斷剩餘值是否匹配
if (root.left == null && root.right == null) {
return sum == root.val;
}
// 遞歸檢查左右子樹,目標和遞減
return hasPathSum(root.left, sum - root.val)
|| hasPathSum(root.right, sum - root.val);
}
}
複雜度分析:
核心思路:使用隊列同時存儲節點與從根到該節點的路徑和。層序遍歷,遇到葉子節點檢查路徑和是否等於目標值。
class Solution {
public boolean hasPathSum(TreeNode root, int sum) {
if (root == null) return false;
Queue nodeQueue = new LinkedList<>();
Queue sumQueue = new LinkedList<>();
nodeQueue.offer(root);
sumQueue.offer(root.val);
while (!nodeQueue.isEmpty()) {
TreeNode node = nodeQueue.poll();
int currentSum = sumQueue.poll();
// 遇到葉子節點,檢查路徑和
if (node.left == null && node.right == null) {
if (currentSum == sum) return true;
}
if (node.left != null) {
nodeQueue.offer(node.left);
sumQueue.offer(currentSum + node.left.val);
}
if (node.right != null) {
nodeQueue.offer(node.right);
sumQueue.offer(currentSum + node.right.val);
}
}
return false;
}
}
複雜度分析:
同樣可用棧模擬遞歸,適合不想用遞歸且偏好深度優先的場景:
class Solution {
public boolean hasPathSum(TreeNode root, int sum) {
if (root == null) return false;
Deque nodeStack = new ArrayDeque<>();
Deque sumStack = new ArrayDeque<>();
nodeStack.push(root);
sumStack.push(root.val);
while (!nodeStack.isEmpty()) {
TreeNode node = nodeStack.pop();
int currentSum = sumStack.pop();
if (node.left == null && node.right == null && currentSum == sum) {
return true;
}
if (node.right != null) {
nodeStack.push(node.right);
sumStack.push(currentSum + node.right.val);
}
if (node.left != null) {
nodeStack.push(node.left);
sumStack.push(currentSum + node.left.val);
}
}
return false;
}
}
left == null && right == null,單側有子節點不算葉子root == null 直接返回 false本題是樹形 DP 的入門範例,掌握「路徑和」狀態傳遞模式,對後續解決「路徑總和 II/III」、「最大路徑和」等進階題目極有幫助。