摘要:先走一步啦力扣路径总和,对解题代码的深入思考思考的问题记一次对该解题代码的位置摆放和的深入思考。举个例子可以看到当进入右子树时,此时为,就返回了,显然并不是正确的答案。
// carl哥的回溯解题法,// 略微有些改动,其实就是把 // return traversal(root, targetSum-root.val);// 的targetSum-root.val,放在了外面,对我来说这更清晰些class Solution { public boolean hasPathSum(TreeNode root, int targetSum) { if(root==null){ return false; } // 先走一步啦 targetSum-=root.val; return traversal(root, targetSum); } private boolean traversal(TreeNode root, int count){ if(root.left==null && root.right==null && count==0){ // 当为叶子节点时,如果count为0就返回true return true; } if(root.left!=null){ count-=root.left.val; if(traversal(root.left, count)){ return true; } count+=root.left.val; } if(root.right!=null){ count-=root.right.val; if(traversal(root.right, count)){ // 如果子树找到了,那就直接返回true return true; } count+=root.right.val; } return false; }}
终止条件是root位于叶子结点才终止(这里先不讨论count)
如果root为null作为终止条件,是会判错的。
举个例子
1 targetsum=1
2
可以看到当进入右子树时,
此时为null,就返回true了,显然并不是正确的答案。
我们再来讨论count
count 也是我们判断是否是正确路径的条件之一
如果count为0时正确,那么需要提前减去当前节点值,
也就是进入循环之前减去root值。
举个例子
1 targetsum=1 只有一个根节点的树
/ /
[1]就是一条路径,如果我们不先减去root的值,
那么进入回溯的if判断就不会成功返回true
有同学可能会想我把减去当前root值的条件放在这里怎么样
当然是可以的,只不过我们需要对整道题作些调整。
class Solution { public boolean hasPathSum(TreeNode root, int targetSum) { if(root==null){ return false; } count=targetSum; return traversal(root); } int count; private boolean traversal(TreeNode root){ count-=root.val; if(root.left==null && root.right==null && count==0){ // 当为叶子节点时,如果count为0就返回true return true; } if(root.left!=null){ if(traversal(root.left)){ return true; } count+=root.left.val; } if(root.right!=null){ if(traversal(root.right)){ // 如果子树找到了,那就直接返回true return true; } count+=root.right.val; } return false; }}
我们首先选择把位于这里的代码删去,如果不删去的话进入下一层循环就相当于减去了两次root.left.val
然后我们要把count变成全局变量,因为位于函数参数的count是一个局部变量,它在下一层函数中减去了root.left.val
,count+=root.left.val
的目的就是为了把它加回来。然而如果他是局部变量,我们就加在了本层函数的局部变量count里,而不是下层函数的count。
那么把count+=root.left.val
,变成count+=root.val
行不行呢,当然是不行的,因为这层函数减去的root.val
是上一层函数的root.left.val
。
根节点刚进来时属于一种特殊情况。
如果count为root.val
时正确
class Solution { public boolean hasPathSum(TreeNode root, int targetSum) { if(root==null){ return false; } return traversal(root, targetSum); } private boolean traversal(TreeNode root, int count){ if(root.left==null && root.right==null && count==root.val){ // 当为叶子节点时,如果count为root.val就返回true return true; } if(root.left!=null){ count-=root.val; if(traversal(root.left, count)){ return true; } count+=root.val; } if(root.right!=null){ count-=root.val; if(traversal(root.right, count)){ // 如果子树找到了,那就直接返回true return true; } count+=root.val; } return false; }}
总结:使用递归解题,代码的摆放位置和终止条件的选择都对编码方式有着巨大的影响
个人感悟:对一颗树的完整思考是,从根节点出发,到左子树,进入下一层循环,看一眼终止条件,就可以回到上一层循环,不用在继续往下走了,就可以验证解题代码是否正确的
get到的点
]
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/123603.html
摘要:月下半旬攻略道题,目前已攻略题。目前简单难度攻略已经到题,所以后面会调整自己,在刷算法与数据结构的同时,攻略中等难度的题目。 Create by jsliang on 2019-07-30 16:15:37 Recently revised in 2019-07-30 17:04:20 7 月下半旬攻略 45 道题,目前已攻略 100 题。 一 目录 不折腾的前端,和咸鱼有什么区别...
阅读 602·2021-11-22 15:32
阅读 2703·2021-11-19 09:40
阅读 2264·2021-11-17 09:33
阅读 1236·2021-11-15 11:36
阅读 1837·2021-10-11 10:59
阅读 1448·2019-08-29 16:41
阅读 1720·2019-08-29 13:45
阅读 2117·2019-08-26 13:36