刷刷刷 Day 18 | 路径总和
112. 路径总和
LeetCode题目要求
给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。
叶子节点 是指没有子节点的节点。
示例
输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
解释:等于目标和的根节点到叶节点路径如上图所示。
解题思路
本地要计算的事从根节点到叶子节点路径的和是否符合targetSum,是不是想到了之前的 257. 二叉树的所有路径 这个题,那么是不是可以对这个题稍作修改,找到所有路径后来计算他们的和是否符合 targetSum。其实这样做的话,并不是太优,因为我们要找到所有路径。而本题其实只要找到其中一个符合的就可以,也就是不需要遍历出所有的路径。
那么本题可以采用前序遍历的方式,并不断的用 targetSum 减去节点值,当差为 0 且节点为叶子节点时就找到了
上代码
class Solution {
public boolean hasPathSum(TreeNode node, int targetSum) {
if (node == null) {
return false;
}
targetSum -= node.val;
// 叶子节点路径的和是否符合 targetSum
if (node.left == null && node.right == null) {
return targetSum == 0;
}
// 处理左子树,如果和符合 targetSum, 返回true
if (node.left != null) {
if (hasPathSum(node.left, targetSum)) {
return true;
}
}
// 处理右子树,如果和符合 targetSum, 返回true
if (node.right != null) {
if (hasPathSum(node.right, targetSum)) {
return true;
}
}
return false;
}
}
重难点
前序遍历,递归,回溯。 这里回溯实际是隐藏了起来。可以通过 debug 模式来自己理解下
113. 路径总和 II
LeetCode题目要求
给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
叶子节点 是指没有子节点的节点。
示例
输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出:[[5,4,11,2],[5,8,4,5]]
解题思路
本题类似于 112. 路径总和。稍微复杂的是需要所有的路径,其实这个题可以采用这个题 257. 二叉树的所有路径 ,找到所有路径后来计算他们的和是否符合 targetSum,把符合的都输出就是结果了。
上代码
class Solution {
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
List<List<Integer>> res = new ArrayList<>();
List<Integer> paths = new ArrayList<>();
traversal(root, targetSum, res, paths);
return res;
}
private void traversal(TreeNode node, int targetSum, List<List<Integer>> res, List<Integer> paths) {
if (node == null) {
return;
}
//前序遍历,先是中节点
paths.add(node.val);
// 是否叶子节点
if (node.left == null && node.right == null) {
// 如果符合目标值,需要将值放入到 结果集,由于需要找到过个路径,这里不能变化 targetSum 的值
if (targetSum - node.val == 0) {
res.add(new ArrayList<>(paths));
}
return;
}
if (node.left != null) {
// 由于需要找到过个路径,这里不能变化 targetSum 的值
traversal(node.left, targetSum - node.val, res, paths);
// 回溯
paths.remove(paths.size() - 1);
}
if (node.right != null) {
// 由于需要找到过个路径,这里不能变化 targetSum 的值
traversal(node.right, targetSum - node.val, res, paths);
// 回溯
paths.remove(paths.size() - 1);
}
}
}
重难点
前序遍历,递归,回溯。递归不需要返回值
附:学习资料链接