题干
输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)
思路
- 首先第一步而言,我们应该明白对于树的操作来言时候,遍历些许都是使用到栈与队列较多,对于树的查询,涉及到左右不定变化一般都是递归。
- 然后对于递归而言要判断我们如何以及何时将正确的路径加入到我们的结果集中。因为题目中说到,打印的是路径,而路径又是从根节点到叶结点–即对于一个节点来说左右子树都为空的情况下就是叶子节点我们就可以对其进行一个基础的判断。
- 输出的是
ArrayList<ArrayList<Integer>>
类型,就需要我们对于每一个的结果集进行加入,然后对于内部的ArrayList<Integer>
进行生成一个新的,一般对于输出结果是ArrayList<ArrayList<Integer>>
时候我们可以这样进行操作。
ArrayList<ArrayList<Integer>> array=new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> list=new ArrayList<Integer>();
list.add(XX);
array.add(list);
list=new ArrayList<Integer>();
- 然后成功之后,例如我们已经知道了一条路径,在添加完成以后,要删除刚刚添加进来的,因为还要进行下一个结点的探索(后序在出现此类问题时候会继续深入的讲解)
- 然后就是左右递归探索即可。
代码
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
// [[10,5,7],[10,12]]
}
*/
import java.util.ArrayList;
public class Solution {
public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
ArrayList<ArrayList<Integer>> array=new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> list=new ArrayList<Integer>();
if(root==null || target==0)
return array;
sum(root,target,array,list,0);
return array;
}
private void sum(TreeNode t,int target,ArrayList<ArrayList<Integer>> array,ArrayList<Integer> list,int sum){
if(t==null || target==0)
return ;
sum=sum+t.val;
if( t.left==null&& t.right==null)
{
if(sum==target){
list.add(t.val);
array.add(new ArrayList<Integer>(list));
list.remove(list.size()-1);
}
return;
}
list.add(t.val);
sum(t.left,target,array,list,sum);
sum(t.right,target,array,list,sum);
// 这个remove会在当上面的两个都遍历完成以后 顺序执行下来。
list.remove(list.size()-1);
}
}
后记
在完成剑指Offer之后,还刷到了牛客上LeetCode经典题目其中有两个题目觉得和路径问题相识,这里也放出来一起讲解一下
path-sum
给定一个二叉树和一个值sum,判断是否有从根节点到叶子节点的节点值之和等于sum的路径,
例如:
给出如下的二叉树,sum=22。
5
4 8
11 13 4
7 2 5 1
思路
- 对于这个题目而言同样是根节点到叶子节点,所以还是判断对于左右节点都为空时表示叶子节点,进行路径值的判断
- 然后传参时候进行相减传参可以不用额外定义变量进行值存取,减少了工作量。
- 因为没有进行值的存取,所以不存在上面的对remove操作。
代码
public class Solution {
public boolean hasPathSum(TreeNode root, int sum) {
if(root==null) return false;
if(root.left==null && root.right==null){
if(sum-root.val==0)
return true;
else return false;
}
return hasPathSum(root.left,sum-root.val)||hasPathSum(root.right,sum-root.val);
}
}
path-sum-II
就是上面的剑指Offer二十四
binay-tree-maximum-path-sum
给定一个二叉树,请计算节点值之和最大的路径的节点值之和是多少。
这个路径的开始节点和结束节点可以是二叉树中的任意节点
例如:
给出以下的二叉树,
1
2 3
思路
- 本题的难点在于我们开始的节点是任意的节点,同时题目中隐约的表示是可能会出现有负值就有点类始于给定你一个数组,其中有正有负,让你判断连续和的最大值,就需要我们对进行相加的值进行一个与0比的操作,判断我们当前的序列值能否加入我们想得到结果的序列,就是说我们最后想得到的最大值能否包括我们此时遍历到的值。
- 同样是递归进行操作,需要与零值进行比较,若是大于零就加入到我们想要的结果中,然后维持一个全局的变量。
- 返回值是判断以当前节点为根的节点的左右子树和是否大于零,若是表示成功则加上当前的值,否则进行抛弃直接返回当前值,对之前就算较大值是小于零进行抛弃。
代码
public class Solution {
int max_m=Integer.MIN_VALUE;
public int maxPathSum(TreeNode root) {
getMax(root);
return max_m;
}
private int getMax(TreeNode root){
if(root==null)
return 0;
int sum=root.val;
int left=getMax(root.left);
int right=getMax(root.right);
if(left>0){
sum+=left;
}
if(right>0){
sum+=right;
}
max_m=Math.max(max_m,sum);
return Math.max(left,right)>0?root.val+Math.max(left,right): root.val;
}
}