持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,点击查看活动详情
题目
给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true
;否则,返回 false
叶子节点 是指没有子节点的节点。
示例 1:

输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
解释:等于目标和的根节点到叶节点路径如上图所示。
示例 2:

输入:root = [1,2,3], targetSum = 5
输出:false
解释:树中存在两条根节点到叶子节点的路径:
(1 --> 2): 和为 3
(1 --> 3): 和为 4
不存在 sum = 5 的根节点到叶子节点的路径。
示例 3:
输入:root = [], targetSum = 0
输出:false
解释:由于树是空的,所以不存在根节点到叶子节点的路径。
提示:
- 树中节点的数目在范围
[0, 5000]内 -1000 <= Node.val <= 1000-1000 <= targetSum <= 1000
解题
解题一:递归
思路
从根节点到叶子节点的值是否满足目标整数 targetSum,我们可以将问题拆分为
- 左子树是否存在满足目标整数 targetSum - 根节点值的路径
- 右子树是否存在满足目标整数 targetSum - 根节点值的路径
- 只要前面两个节点其中一个满足,则总体满足
- 再进一步,我们将根节点泛化为当前节点,这样通过递归的方式就可以判断是否存在满足条件的路径
代码
/**
* Definition for a binary tree node.
*/
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
if (root == null) {
return false;
}
if (root.left == null && root.right == null) {
return root.val == targetSum;
}
return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val);
}
}
总结
性能分析
- 执行耗时:0 ms,击败了 100.00% 的 Java 用户
- 内存消耗:41.6 MB,击败了 5.06% 的 Java 用户
解题二:广度优先搜索
思维
使用两个队列,一个队列 nodeStack 存放节点,一个 resultStack 存放跟节点到 nodeStack 对应节点的距离
- 将根节点存入 nodeStack,根节点的值存入 resultStack
- 取出 nodeStack 和 resultStack 的值
- 如果取出的节点不是叶子节点,则继续进行存放 nodeStack 和 resultStack 操作
- 如果取出的节点是叶子节点,判断和目标整数 targetSum 是否相等
代码
import java.util.Stack;
/**
* Definition for a binary tree node.
*/
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
if (root == null) {
return false;
}
Stack<TreeNode> nodeStack = new Stack<>();
Stack<Integer> resultStack = new Stack<>();
nodeStack.push(root);
resultStack.push(root.val);
while (!nodeStack.isEmpty()) {
TreeNode pop = nodeStack.pop();
Integer tempResult = resultStack.pop();
// 计算孩子节点的值
if (pop.left != null) {
nodeStack.push(pop.left);
resultStack.push(tempResult + pop.left.val);
}
if (pop.right != null) {
nodeStack.push(pop.right);
resultStack.push(tempResult + pop.right.val);
}
if (pop.left == null && pop.right == null) {
// 叶子节点,判断是否满足条件
resultStack.push(tempResult);
}
}
return resultStack.contains(targetSum);
}
}
总结
性能分析
- 执行耗时:2 ms,击败了 6.97% 的 Java 用户
- 内存消耗:41.3 MB,击败了 46.27% 的 Java 用户