剑指Offer(Java版):二叉树中和为某一值的路径

题目:输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的全部路径。从树的根节点开始往下一直到叶结点所通过的全部的结点造成一条路径。java

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

通常的数据结构和算法的教材都没有介绍树的路径,所以对大多数应聘者而言,这是一个新概念,也就很难一会儿想出完整的解题思路。这个时候咱们能够试着从一两个具体的例子入手,找到规律。算法

以图中的二叉树为例分析,因为路径是从根节点出发到叶结点,也就是说路径是以根节点为起始点,所以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,所以这也是一条符合条件的路径。.net

总结过程以下:指针

分析完前面的具体的例子以后,咱们就找到了一些规律。当用前序遍历的方式访问到某一节点时,咱们把该结点添加到路径上,并累加该结点的值。若是该结点为叶结点而且路径中结点值的和恰好为输入的整数,则当前的路径符合要求,咱们把它打印出来。若是当前的结点不是叶结点,则继续访问它的子节点。当前结点访问结束后,递归函数将自动回到它的父节点。所以咱们在函数退出以前要在路径上删除当前结点并减去当前结点的值,以确保返回父节点时路径恰好是从根节点到父节点的路径。咱们不难看出保存路径的数据结构其实是一个栈,所以路径要与递归调用状态一致,而递归调用的本质上是一个压栈和出栈的过程。递归

Java代码实现:get

package cglib;

import java.util.Stack;

class BinaryTreeNode{
    int value;
    BinaryTreeNode leftNode;
    BinaryTreeNode rightNode;
    
    

}

public class DeleteNode {
    public  void findPath(BinaryTreeNode root,int sum){
        if(root==null)
        return;
        Stack<Integer> stack=new Stack<Integer>();
        int currentSum=0;
        findPathd(root,sum,stack,currentSum);
        }
        private  void findPathd(BinaryTreeNode root, int sum, Stack<Integer> stack,int currentSum) {
        System.out.println("根结点值"+root.value);
        currentSum+=root.value;
        stack.push(root.value);
        if(root.leftNode==null&&root.rightNode==null){
        if(currentSum==sum){
        System.out.println("找到一个路径");
        for(int path:stack){
        System.out.print(path+" ");
        }
        System.out.println();
        }
        }
        if(root.leftNode!=null){
            System.out.println("左结点值"+root.leftNode.value);
        findPathd(root.leftNode, sum, stack, currentSum);
        }
        if(root.rightNode!=null){
            System.out.println("右结点值"+root.leftNode.value);
        findPathd(root.rightNode, sum, stack, currentSum);
        }
        int t=stack.pop();
        System.out.println("出栈值="+t);
        }
    public static void main(String[] args) throws Exception{  
        BinaryTreeNode root1=new BinaryTreeNode();
        BinaryTreeNode node1=new BinaryTreeNode();
        BinaryTreeNode node2=new BinaryTreeNode();
        BinaryTreeNode node3=new BinaryTreeNode();
        BinaryTreeNode node4=new BinaryTreeNode();
        root1.leftNode=node1;
        root1.rightNode=node2;
        node1.leftNode=node3;
        node1.rightNode=node4;
        root1.value=10;
        node1.value=5;
        node2.value=12;
        node3.value=4;
        node4.value=7;
        DeleteNode testFindPath=new DeleteNode();
        testFindPath.findPath(root1, 22);
        }
        
    } 

 

输出:

根结点值10 左结点值5 根结点值5 左结点值4 根结点值4 出栈值=4 右结点值4 根结点值7 找到一个路径 10 5 7 出栈值=7 出栈值=5 右结点值5 根结点值12 找到一个路径 10 12 出栈值=12 出栈值=10

相关文章
相关标签/搜索