告诫自己:贵在坚持!
过程要注重自己的思考
借助图了解过程,动手写,动脑思考
目录
1,题目
给你二叉树的根节点 root
和一个表示目标和的整数 targetSum
。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum
。如果存在,返回 true
;否则,返回 false
。
叶子节点 是指没有子节点的节点。
2,代码
2-0递归 -我的错误代码
/**
* 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 === null ){
return targetSum === 0;
}
if(root.right === null ||root.left === null){
return root.val === targetSum;
}
return hasPathSum(root.left,targetSum-root.val) && hasPathSum(root.right,targetSum-root.val)
};
错误分析:
-
基础情况处理不当:在
if(root === null )
的情况下,直接返回targetSum === 0
是不正确的。正确的基础情况应该是当遍历到一个空节点(null
)时,直接返回false
,因为空节点不代表路径的终点,而只是表示没有子节点存在。 -
叶节点的判断逻辑错误:
if(root.right === null || root.left === null)
的条件判断逻辑是错误的。这里的逻辑应该是当当前节点为叶节点(即root.left === null && root.right === null
)时,检查targetSum
是否等于当前节点的值root.val
。而代码中的逻辑只要当前节点缺少一个子节点就进行判断,这忽略了二叉树的性质,即叶节点是没有任何子节点的节点。 -
逻辑运算符使用错误:
return hasPathSum(root.left,targetSum-root.val) && hasPathSum(root.right,targetSum-root.val)
使用的是逻辑与&&
运算符,这意味着左右子树的路径和都必须符合条件,这与题目要求不符。题目的要求是找到至少一条符合条件的路径,因此应该使用逻辑或||
运算符。
2.1递归思想
假设从根节点到当前节点的值之和是val,则我们可以将问题转化为:是否存在当前节点的子节点到叶子节点的路径,满足路径之和为sum - val;
/**
* 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 === null ){
return false;
}
// 叶子节点的判断
if(root.right === null && root.left === null){
return root.val === targetSum;
}
// 存在一条路径即可
return hasPathSum(root.left,targetSum-root.val) || hasPathSum(root.right,targetSum-root.val)
};
2.2广度优先搜索
自己看图实现逻辑代码
使用两个队列,分别存储将要遍历的节点,以及根节点到这些节点的路径和即可。
/**
* 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===null){
return false;
}
let queue_nodes=[];
let queue_vals=[];
queue_nodes.push(root);
queue_vals.push(root.val);
while(queue_nodes.length > 0){
let temNode = queue_nodes.shift();
let temSum = queue_vals.shift();
if(temNode.left === null && temNode.right === null){
if(temSum === targetSum) return true;
}
if(temNode.left != null){
queue_nodes.push(temNode.left);
const sum = temSum + temNode.left.val;
queue_vals.push(sum);
}
if(temNode.right != null){
queue_nodes.push(temNode.right);
const sum = temSum + temNode.right.val;
queue_vals.push(sum);
}
}
return false;
};
3,学习与总结
3.1,叶子节点的判断
if(temNode.left === null && temNode.right === null)
节点没有左孩子且没有右孩子