这道题感觉就像是一开始的路径总和的升级版,首先这道题放宽了限制条件,就是求路径和的时候不要求必须从根节点开始,也不要求必须到叶子节点结束,这两点就对我们的递归限制条件造成了很大的影响,先看下代码是怎么解决这个问题的,因为我本人也想不出来,代码也是参考别人的答案然后自己领会其中精髓
public int pathSum(TreeNode root, int sum) { if(root == null) return 0; int ret = pathSumStartWithRoot(root,sum) + pathSum(root.left, sum) + pathSum(root.right, sum); return ret; } public int pathSumStartWithRoot(TreeNode root, int sum) { if(root == null) return 0; //val不可能相等,左右又没有,所以直接返回0就完事 int ret = 0; if( root.val == sum) ret++; ret += pathSumStartWithRoot(root.left,sum-root.val) + pathSumStartWithRoot(root.right, sum -root.val); return ret; }
这道题其实可以这么来思考,因为他是路径那个题目的限制条件放宽版,所以我们可以考虑限制条件放宽对递归的出口和边界条件带来了什么影响呢?
1、不一定从根节点开始,就是说任何一个节点都有可能是你开始计算路径和的起始节点,那么这对递归代码造成的影响就是,你开始计算必须考虑到所有节点,
就是这句 ret = pathSumStartWith(root,sum) + pathSum(root.left,sum) + pathSum(root.right,sum);
从根节点开始,它的每一个左右子节点都要进行一次root节点层级的新递归计算,也就是说这个操作可以看作是一个两层的递归,而上面这句代码解决的是第一层的涉及到所有可能节点的问题;
有了这句改造就可以覆盖不一定是从根节点开始这个条件了;
2、也不一定是子节点结束。这个条件和路径之和1比起来就比较6,因为它直接将递归到叶子节点再判断的这个完整的调用链过程打散了。
看代码:
public int pathSumStartWithRoot(TreeNode root, in sum) { if(root == null) return 0; int ret =0; if(root.val == sum) ret++; ret += pathSumStartWithRoot(root.left,sum-root.val) + pathSumStartWithRoot(root.right,sum-root.val); return ret; }
这个递归过程可以看作是二级递归就是收集节点路径的基层员工,它是以每个节点的角度出发来实现收集,如果自身等于,那么久+1,再递归判断左右子节点是否等于自己-root.val
这种过程类似于fork/join框架,完成整个收集过程;