二叉树中和为某一值的路径

题目描述

输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。


思路分析

        如下图,输入二叉树和整数22,则打印出两条路径,第一条路径包含结点10,12,第二条路径包含的结点为10,5,7。


        以图中的二叉树为例分析,由于路径是从根节点出发到叶结点,也就是说路径是以根节点为起始点,因此i我们首先需要遍历根节点。在树的前序、中序、后序三种遍历方式中,只有前序遍历是首先访问根节点的。

        按照前序遍历的顺序遍历途中的二叉树,在访问结点10之后,就会访问结点5.从二叉树结点的定义可以看出,在本题的二叉树结点中没有指向父节点的指针,访问到结点5的时候,我们是不知道前面经过了哪些结点的,除非我们把经过的路径上的结点都保存起来。每访问到一个结点的时候,我们都把当前的结点添加到路径中去。到达结点5时,路径中包含两个结点,他们的值分别是10和5.接下来遍历到结点4,我们把这个结点也添加到路径中,这个时候已经到达了叶结点,但路径上三个结点的值之和为19.这个和不等于输入的值22,因此不符合要求的路径。

        我们接着要遍历其他的结点。在遍历下一个节点之前,先要从结点4回到结点5,再去遍历结点5的右子节点7.值得注意的是,回到结点5的时候,由于结点4已经不在前往结点7的路径上了,我们需要把结点4从路径中删除。接下来访问到结点7的时候,再把结点添加到路径中。此时路径中三个结点10,5,7之和刚好是22,是一条符合要求的路径。

        我们最后要遍历的结点是12.在遍历这个结点之前,需要先经过结点5回到结点10.同样,每一次当从子节点回到父节点的时候,我们都需要在路径上删除子节点。最后从结点10到达结点12的时候,路径上的两个结点的值之和也是22,因此这也是一条符合条件的路径。

          总结上述思路:
    (1)若根节点的值大于给定的值或者根节点为空,则清空路径;
    (2)若根节点的值等于给定的值,需要判断当前节点是否为叶子节点,若为叶子节点,则是需要找的一条路径,若不是,将保存的节点全部清空。
    (3)若根节点的和小于给定的值,则递归地访问其左右子树。


Java实现

import java.util.ArrayList;
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
        //ArrayList<ArrayList<Integer>>用来存储所有的路径集合
        ArrayList<ArrayList<Integer>> pathlist=new ArrayList<ArrayList<Integer>>();
        //判断特殊输入
        if(root==null||root.val>target)
            return pathlist;
        //用ArrayList<Integer>存储一条路径
        ArrayList<Integer> path=new ArrayList<Integer>();
        findPath(root,target,pathlist,path);
        return pathlist;
    }
    
    public void findPath(TreeNode root,int target,ArrayList<ArrayList<Integer>> pathlist,ArrayList<Integer> path){
        //如果root为空或者root.val>target,则此路径必不满足要求,清空此路径
        if(root==null||root.val>target)
            path.clear();
        //如果root.val==target,则判断此结点是否为叶子结点
        //如果是叶子结点则将此结点值插入路径中,而且意味着这条路径已经结束,将这条path加入到pathlist中
        //如果不是叶子结点,则此路径必然不符合要求,清空此路径
        else if(root.val==target){
            if(root.left==null&&root.right==null){
                path.add(root.val);
                pathlist.add(path);
            }
            else 
                path.clear();
        }
        //如果root.val<target,则先将root添加到path中,然后递归遍历其左右子树,找到合适的路径
        else{
            path.add(root.val);
            target=target-root.val;
            //新建立一条路径,用于遍历右子树,因为是从根结点分支的,所以初始的path2中的元素与path相同
            ArrayList<Integer> path2=new ArrayList<Integer>();
            path2.addAll(path);
            findPath(root.left,target,pathlist,path);
            findPath(root.right,target,pathlist,path2);
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值