题目描述:
给你二叉树的根节点 root
和一个表示目标和的整数 targetSum
。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum
。如果存在,返回 true
;否则,返回 false
。
叶子节点 是指没有子节点的节点。
输入: root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出: true
解释: 等于目标和的根节点到叶节点路径如上图所示。
我原来是这么写的:
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @param {number} targetSum
* @return {boolean}
*/
var hasPathSum = function(root, targetSum) {
let sum = 0;
let res = [];
if(!root){
res.push(sum);
sum = 0;
return false;
}
// 用前序遍历
let preDfs = function (root) {
let nodeVal = root.val;
sum += nodeVal;
if(root.left) {
preDfs(root.left);
}
if(root.right) {
preDfs(root.right);
}
}
preDfs(root);
if(res.indexOf(targetSum) !== -1){
return true;
} else {
return false;
}
};
要获取路径总和,肯定少不了遍历,我采用的前序遍历。
我本来是想,遍历每一条路径,然后把每条路径上的节点加和,依次push到一个数组中,最后再遍历这个数组,如果数组里面有和targetSum相等的数,那就说明存在这样的路径满足总和为targetSum。
然而测试用例只通过了一半。。。加和比对的方式也比较费劲儿
看了 代码随想录 的思路之后,豁然开朗
用递减的思路来做这道题,会更简易一些,思路也比较好理解
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @param {number} targetSum
* @return {boolean}
*/
var hasPathSum = function(root, targetSum) {
if(!root)return false;
let tranversal = (sum, node) => {
// 递归的终止条件
if(!node.left && !node.right && sum == 0)return true; // 叶子节点且满足targetSum
if(!node.left && !node.right)return false;
// 单层递归逻辑 and 递归终止条件
if (node.left && tranversal(sum - node.left.val, node.left)) {
// 需要传递节点
return true;
}
if (node.right && tranversal(sum - node.right.val, node.right)) {
return true;
}
return false;
}
return tranversal(targetSum - root.val, root);
};
需要注意的是,在 单层递归逻辑 中,有个比较不好理解的地方:
在单层递归的判断条件中,有个 tranversal(sum - node.left.val, node.left)
这行代码其实是把上面的if(!node.left && !node.right && sum == 0)return true;
这个return结果拿过来做判断了
意思是,存在node.left
的同时,我们对这个左子节点做tranversal的计算,如果满足叶子节点且targetSum减到最后的结果也为0(即这个判断条件为true),那么就在下面的单层递归逻辑中返回true
这个tranversal里面的操作可以理解为一个回溯
借用代码随想录的图:
最后顺便总结一下,递归三部曲
- 确定递归要不要有返回值,如果有,返回啥,返回什么类型
- 确定递归的结束条件
- 确定单层递归的逻辑
🌸 🌸 🌸完结撒花 🌸 🌸 🌸