题目描述
输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。
基本思路
设二叉树为{10,5,12,4,7},和为22,则打印出两条路径,第一条路径为10,12,第二条路径为10,5,7。使用前序遍历的方法访问到某一节点时,我们把该节点添加到路径上,并累加该节点的值。如果该节点为叶子节点(即该节点的左右子节点均为null)并且路径中节点值的和刚好等于输入的整数,则当前的路径符合要求,我们把它打印出来。如果当前节点不是叶结点,则继续访问它的子节点。当前访问结束后,递归函数将自动回到它的父节点。因此我们在函数退出之前要在路径上删除当前节点并减去当前节点的值,以确保返回父节点的路径刚好是从根节点到父节点的路径。不难看出保存路径的数据结构实际上是一个栈,因为路径要与递归调用状态一致,而递归调用的本质就是一个压栈和出栈的过程。
Java代码
package com.swordOffer.pathInTree16;
import java.util.ArrayList;
/**
* Created by Feng on 2017/5/14.
* 输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。
* 路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。
*/
public class PathInTree {
//存储节点的值
static ArrayList<Integer> list = new ArrayList<Integer>();
//存储路径
static ArrayList<ArrayList<Integer>> listAll = new ArrayList<ArrayList<Integer>>();
public static void main(String[] args) {
TreeNode node1 = new TreeNode(10);
TreeNode node2 = new TreeNode(5);
TreeNode node3 = new TreeNode(12);
TreeNode node4 = new TreeNode(4);
TreeNode node5 = new TreeNode(7);
node1.left = node2;
node1.right = node3;
node2.left = node4;
node2.right = node5;
ArrayList<ArrayList<Integer>> result = findPath(node1, 22);
for (ArrayList<Integer> list : result) {
for (Integer integer : list) {
System.out.print(integer + " ");
}
}
}
public static ArrayList<ArrayList<Integer>> findPath(TreeNode root, int target) {
if (root == null) {
return listAll;
}
//添加根节点
list.add(root.val);
//当前目标的值为减去根节点后的值
target -= root.val;
//如果节点为叶子节点且路径的值和目标的值相等
if (target == 0 && root.left == null && root.right == null) {
listAll.add(new ArrayList<>(list));
}
//采用递归,回到父节点
findPath(root.left, target);
findPath(root.right, target);
//删除当前节点
list.remove(list.size() - 1);
return listAll;
}
}
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
}