剑指offer之面试题25:二叉树中和为某一值的路径

题目描述

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

举个例子分析一下

            10
           /  \
          5   12
         / \  
        4  7 

和为22的路径有两条:{10,5,7},{10,12}

怎么得到的?
首先需要先遍历每个结点,(因为路径定义是根结点到叶结点所经过的结点形成的路径,故需要先遍历根结点,二叉树的前序遍历、中序遍历、后序遍历中只有前序遍历符合)。因为二叉树没有指向父结点的指针,所以每次走过一个结点,需要保存在临时变量里。直到遍历到叶结点,计算临时结点形成的路径的和,如果满足,则将该路径保存(路径不止一条)。如果不满足,则逐个移除结点,回到父节点,然后切换到右孩子,重新计算路径和,如果还不满足,则继续向祖父结点回溯,…,递归。

步骤操作是否为叶结点路径路径结点值的和
1访问结点10{10}10
2访问结点5{10,5}15
3访问结点4{10,5,4}19,叶子结点但不符合,移除4
4回到结点5{10,5}15
5访问结点7{10,5,7}22,叶子结点符合,将路径保存
6回到结点5{10,5}15
7回到结点10{10}10
8访问结点12{10,12}22,叶子结点符合,将路径保存

总结一下:前序遍历到某个结点,将结点添加到路径上,并计算路径当前值的和,如果当前结点为叶子结点且和恰好为输入的值,则符合要求将路径保存。如果不是叶子结点,则继续访问其孩子。当前结点访问结束,递归函数自动回到其父结点,在此之前要移除当前结点以及结点值。其实这就是递归栈的压入和出栈。

代码如下:

/**
 * 
 */
package com.su.biancheng;

import java.util.ArrayList;


/**
 * @title FindPath.java
 * @author Shuai
 * @date 2016-4-27下午4:43:13
 */
public class FindPath {
    public static class TreeNode {
        int val = 0;
        TreeNode left = null;
        TreeNode right = null;

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

        }
    }
    public static ArrayList<ArrayList<Integer>> FindPath(TreeNode root, int target) {
        ArrayList<ArrayList<Integer>> list=new ArrayList<ArrayList<Integer>>();
        if(root==null)
            return list;
        ArrayList<Integer> path=new ArrayList<Integer>();
        int currentSum=0;
        return FindPath(root,target,list,path,currentSum);
    }
    public static ArrayList<ArrayList<Integer>> FindPath(TreeNode root,
            int target, ArrayList<ArrayList<Integer>> list, ArrayList<Integer> path, int currentSum) {
        currentSum += root.val;
        path.add(root.val);

        //如果是是叶子结点且和等于目标值,则把当前的路径添加到list中
        boolean isLeafNode = root.left == null && root.right == null;
        if(currentSum == target && isLeafNode){
            ArrayList<Integer> nodes = new ArrayList<Integer>();
            //遍历path集合
            for (Integer val : path) {
                nodes.add(val);
            }
            list.add(nodes);
        }

        //如果不是叶子节点,就从其孩子节点寻找
        if(root.left != null){
            FindPath(root.left,target,list,path,currentSum);
        }
        if(root.right != null){
            FindPath(root.right,target,list,path,currentSum);
        }

        //在返回父节点只之前,需要删除当前节点
        Integer val = path.remove(path.size() - 1);
        currentSum -= val;
        return list;
    }
    public static void main(String[] args){
        TreeNode root = new TreeNode(10);
        TreeNode node1 = new TreeNode(5);
        TreeNode node2 = new TreeNode(12);
        TreeNode node3 = new TreeNode(4);
        TreeNode node4 = new TreeNode(7);

        root.left = node1;
        root.right = node2;
        node1.left = node3;
        node1.right = node4;

        System.out.println(FindPath(root,22).toString());
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值