1、路径总和(LeetCode 112)
给你二叉树的根节点 root
和一个表示目标和的整数 targetSum
。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum
。如果存在,返回 true
;否则,返回 false
。
叶子节点 是指没有子节点的节点。
1)示例
提示:
- 树中节点的数目在范围
[0, 5000]
内 -1000 <= Node.val <= 1000
-1000 <= targetSum <= 1000
2)思路
保持递归的思想;假定从根节点到当前节点的值之和为 val
,可以将这个大问题转化为一个小问题:是否存在从当前节点的子节点到叶子的路径,满足其路径和为 sum - val
- 如果当前节点就是叶子节点,直接判断 sum 是否等于 val,但凡有一个就返回true。
- 如果当前节点不是叶子节点,递归地判断它的子节点是否能满足条件。
3)代码
public boolean hasPathSum(TreeNode root, int targetSum) {
if (root == null) {
return false;
}
targetSum -= root.val;
if (root.left == null && root.right == null && targetSum == 0) {
return true;
}
return hasPathSum(root.left, targetSum) || hasPathSum(root.right, targetSum);
}
复杂度分析
时间复杂度:O(N),N 是树的节点数,每个节点都会被访问一次。
空间复杂度:O(H),H 是树的高度。
- 主要取决于递归时栈空间的开销;
- 最坏情况下,树呈现链状,空间复杂度为
O(N)
; - 平均情况下树的高度与节点数的对数正相关,空间复杂度为
O(logN)
。
2、路径总和 II(LeetCode 113)
给你二叉树的根节点 root
和一个整数目标和 targetSum
,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
叶子节点 是指没有子节点的节点。
1)示例
提示:
- 树中节点的数目在范围
[0, 5000]
内 -1000 <= Node.val <= 1000
-1000 <= targetSum <= 1000
2)思路
整体思路和路径总和(LeetCode 112)
一样,区别在于对树进行遍历时,需要额外记录路径(注意在递归的过程中对路径进行回溯)。
3)代码
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
List<List<Integer>> res = new ArrayList<>();
Stack<Integer> temp = new Stack<>();
dfs(root, targetSum, res, temp);
return res;
}
private void dfs(TreeNode root, int targetSum, List<List<Integer>> res, Stack<Integer> temp) {
if (root == null) {
return;
}
targetSum -= root.val;
temp.push(root.val);
if (targetSum == 0 && root.left == null && root.right == null) {
res.add(new ArrayList<>(temp));
}
// 等价于 root.left != null 递归左子树然后回溯,root.right != null 递归右子树然后回溯
dfs(root.left, targetSum, res, temp);
dfs(root.right, targetSum, res, temp);
temp.pop();
}
复杂度分析
时间复杂度:O(N),N 是树的节点数。
- 这里的是均摊时间复杂度。
空间复杂度:O(N),N 是树的节点数。
- 取决于栈空间的开销,栈中的元素个数不会超过树的节点数。
本文含有隐藏内容,请 开通VIP 后查看