一、试题名称:在二叉树中找出和为某一值的所有路径
二、试题描述:
请写一个程序创建一棵二叉树,并按照一定规则,输出二叉树根节点到叶子节点的路径。
规则如下:
1、从最顶端的根结点,到最下面的叶子节点,计算路径通过的所有节点的和,如果与设置的某一值的相同,那么输出这条路径上的所有节点。
2、从根节点遍历树时,请请按照左到右遍历,即优先访问左子树的节点。
二叉树创建规则:从上到下一层一层的,按照从左到右的顺序进行构造
输入"10,5,12,4,7"值,构造的树如下:
1) 10
2) 10
/
5
3) 10
/\
5 12
4) 10
/\
5 12
/
4
5) 10
/\
5 12
/\
4 7
针对上面的二叉树,如果当前我们设置的“路径和”为19,那么输出结果为:
10,5,4
如果有多个路径,按到左到右的顺序遍历生成的结果每行显示一个显示。例如如果当前我们设置的“路径和”为22,那么输出结果为:
10,5,7
10,12
如果没有找到路径和为设置的值的路径,输出error。
三、输入:
输入整数N---路径和
一行字符串,多个正整数,之间用","隔开
四、输出: 满足条件的二叉树路径
五、样例输入:
22 10,5,12,4,7 |
六、样例输出:
10,5,7
10,12
个人对题目的理解:要求寻找的路径是从根节点到叶子节点的完整路径,而不是子路径,基于此,整体使用先序遍历思路,Java实现如下,
首先定义树节点:
class TreeNode{
private int value = 0;
private TreeNode leftChild = null;
private TreeNode rightChild = null;
public TreeNode() {
}
public TreeNode(TreeNode leftChild, TreeNode rightChild, int value) {
this.leftChild = leftChild;
this.rightChild = rightChild;
this.value = value;
}
public TreeNode(int value) {
this(null, null, value);
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public TreeNode getLeftChild() {
return leftChild;
}
public void setLeftChild(TreeNode leftChild) {
this.leftChild = leftChild;
}
public TreeNode getRightChild() {
return rightChild;
}
public void setRightChild(TreeNode rightChild) {
this.rightChild = rightChild;
}
}
然后构造二叉树、查找路径:
import org.apache.commons.collections.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
/**
* by huhaishen
*/
public class FindBinaryTreePath {
/**
* 构建二叉树
* @param intArray 给定的建树的整数数组,形如:{10, 5, 12, 4, 7}
* @return 二叉树根节点
*/
public static TreeNode createBinaryTree(int[] intArray) {
List<TreeNode> nodes = new ArrayList<>();
for (int obj : intArray) {
nodes.add(new TreeNode(obj));
}
TreeNode root = nodes.get(0);//第一个是根节点
for (int i = 0; i < intArray.length / 2; i++) {
nodes.get(i).setLeftChild(nodes.get(2 * i + 1));
if (2 * i + 2 < intArray.length) {//避免偶数的时候,下标越界
nodes.get(i).setRightChild(nodes.get(2 * i + 2));
}
}
return root;
}
/**
* 查找并打印二叉树中满足给定值的路径
* @param root 树根节点
* @param value 给定数值
*/
public static void findAndPrintPath(TreeNode root, int value){
List<String> paths = new ArrayList();//存储查找到的所有路径
List<Integer> onePath = new ArrayList<>();//单个路径,第一个值必定是根节点的值
findPath(root, paths, onePath, value);
if (CollectionUtils.isEmpty(paths)) {
System.out.println("error");
return;
}
paths.stream().forEach(str -> System.out.println(str));
}
/**
* 查找路径
* @param node 树的节点
* @param allPaths 路径集合
* @param onePath 单条路径(每次递归都是不一样的)
* @param inputValue 输入的值
*/
private static void findPath(TreeNode node, List<String> allPaths, List<Integer> onePath, int inputValue){
onePath.add(node.getValue());//当前节点值添加到单条路径,递归过程中层层添加
//利用先序遍历思想
if (null != node.getLeftChild()) {//递归左子树
findPath(node.getLeftChild(), allPaths, onePath, inputValue);
onePath.remove(onePath.size() - 1);//每一次跳出findPath方法都删掉当前路径的最后一个值,层层递减
}
if (null != node.getRightChild()) {//递归右子树
findPath(node.getRightChild(), allPaths, onePath, inputValue);
onePath.remove(onePath.size() - 1);//每一次跳出findPath方法都删掉当前路径的最后一个值,层层递减
}
//当前节点为叶子节点才执行下面逻辑
int sum = 0;
for (Integer value : onePath) {//计算当前路径的值之和
sum += value;
}
if (sum == inputValue) {//若计算结果等于给定值则allPaths记录下当前路径
String s = onePath.toString();
allPaths.add(s.substring(1, s.length() - 1));
}
}
/**
* 测试方法
* @param args
*/
public static void main(String[] args) {
int[] objs = {10, 5, 12, 4, 7};
TreeNode binaryTree = FindBinaryTreePath.createBinaryTree(objs);
findAndPrintPath(binaryTree, 22);
}
}
测试:假如给定的字符串为"10, 5, 12, 4, 7",整数N为22,则测试结果如下,