《剑指Offer》面试题:打印出二叉树中结点值的和为输入整数的所有路径

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

思路

用前序遍历来实现

/*
测试函数编写的要求如下:

输入:
每个测试案例包括n+1行:

第一行为2个整数n,k(1<=n<=10000),n表示结点的个数,k表示要求的路径和,结点编号从1到n。                                                                                                       

接下来有n行。这n行中每行为3个整数vi,leftnode,rightnode,vi表示第i个结点的值,leftnode表示第i个结点的左孩子结点编号,rightnode表示第i个结点的右孩子结点编号,若无结点值为-1。编号为1的结点为根结点。

输出:
对应每个测试案例,先输出“result:”占一行,接下来按字典顺序输出满足条件的所有路径,这些路径由结点编号组成,输出格式参照输出样例。

样例输入:
5 22
10 2 3
5 4 5
12 -1 -1
4 -1 -1
7 -1 -1
1 5
1 -1 -1
样例输出:
result:
A path is found: 1 2 5
A path is found: 1 3
result:
*/


#include<stdio.h>
#include<stdlib.h>

struct TreeNode{
    int mValue;
    int myselfIndex;//自己在树中的节点下标 
    int leftIndex;//左右孩子节点的编号 
    int rightIndex;
};
/*
用数组来保存结果 
*/
TreeNode result[10000]; 

/*
根据前序遍历的方法来寻找满足路径和等于sum的所有路径 
*/

/*
参数的说明
@param treeNode:树节点的保存位置的首地址
@param nodeIndex:此节点在树节点的保存数组中的下标 
@param sum:要求寻找的路径需要满足的总和
@param top:结果数组中的下标,用来将此节点保存其中 
*/
void findThePathInTreeEqualValue(TreeNode *treeNode,int nodeIndex,int sum,int top){
    if(treeNode==NULL||nodeIndex==-1) 
        return;
    //先保存此节点 
    result[top]=treeNode[nodeIndex]; 
    if(treeNode[nodeIndex].leftIndex==-1&&treeNode[nodeIndex].rightIndex==-1){//如果此节点为叶子节点,则进行统计求和看是否此路径满足条件
        int pathSum=0;
        for(int i=0;i<=top;i++){//求和 
            pathSum+=result[i].mValue;
        } 
        //如果求和满足条件则输出 
        if(pathSum==sum){
            printf("A path is found:");
            for(int i=0;i<=top;i++){
                printf("%d  ",result[i].myselfIndex);
            }
            printf("\n");
        } 

    }
    else{//如果此节点不是叶子节点,则继续深入
        //由于需要将结果按字典顺序输出满足条件的所有路径,本来是需要判断一下,
        //但是由于输入控制着我们的节点是从节点1 一行一行的提供输入节点N,因此不存在左孩子的节点编号大于右孩子的节点编号 ,如果要判断,则可以选择下面注释的那几行代码进行完成此功能 
        if(treeNode[nodeIndex].leftIndex!=-1){//其实这里都不需要加此判断,因为在此函数最前面几行也进行了判断。 
            findThePathInTreeEqualValue(treeNode, treeNode[nodeIndex].leftIndex,sum,top+1);//这行与下面一行都是top+1 是保证兄弟节点只能有一个节点值存储在此位置 
        }
        if(treeNode[nodeIndex].rightIndex!=-1){
            findThePathInTreeEqualValue(treeNode, treeNode[nodeIndex].rightIndex, sum,top+1);
        }

         //由于需要将结果按字典顺序输出满足条件的所有路径,因此仅仅上面几行是不行的,需要判断一下 
         //下面就是进行判断,总之是先小后大 
//      if(treeNode[nodeIndex].leftIndex<treeNode[nodeIndex].rightIndex) {// 
//          findThePathInTreeEqualValue(treeNode, treeNode[nodeIndex].leftIndex,sum,top+1);
//          findThePathInTreeEqualValue(treeNode, treeNode[nodeIndex].rightIndex,sum,top+1);
//      }
//      else{
//          findThePathInTreeEqualValue(treeNode, treeNode[nodeIndex].rightIndex, sum,top+1);
//          findThePathInTreeEqualValue(treeNode, treeNode[nodeIndex].leftIndex, sum,top+1);
//      }


    } 

}


int main(void){
    int n;//节点的个数 
    int sum;//和 
    while(scanf("%d%d",&n,&sum)!=EOF){

        //先开辟n个节点的空间,用来存储n个节点的信息
        if(n>0){
            TreeNode*  treeNode=(TreeNode *)malloc(n*sizeof(TreeNode));
            if(treeNode==NULL){
                exit(EXIT_FAILURE);
            } 
            //接收n行数据,即Tree中n个节点的数据 (包括结点值、左右孩子节点的编号) 
            int value;
            int rightIndex;
            int leftIndex;
            for(int i=0;i<n;i++){
                treeNode[i].myselfIndex=i+1; //自己节点的标号 
                scanf("%d%d%d",&value,&leftIndex,&rightIndex);
                treeNode[i].mValue=value;
                if(leftIndex!=-1){
                    treeNode[i].leftIndex=leftIndex-1;//之所以减1,是直接保存该节点在数组中的下标,方便调用 
                }
                else{
                    treeNode[i].leftIndex=-1;
                }

                if(rightIndex!=-1){
                    treeNode[i].rightIndex=rightIndex-1;
                }
                else{
                    treeNode[i].rightIndex=-1;
                }


            }
            printf("result:\n") ;
            findThePathInTreeEqualValue(treeNode,0,sum,0); 
            free(treeNode);

        } 

    }
    return 0;
}

程序运行结果如下

在牛客网上AC的代码如下:

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 {
    ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
    public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
        helper(new ArrayList<Integer>(),root,target);
        return res;
    }
    private void helper(ArrayList<Integer> tempRes,
            TreeNode root, int target) {
        if(root==null){
            return;
        }
        if(root.left==null&&root.right==null){
            if(root.val==target){
                tempRes.add(root.val);
                res.add(tempRes);
            }
            return ;
        }
        tempRes.add(root.val);
        if(root.left!=null){
            helper(new ArrayList(tempRes),root.left,target-root.val);
        }

        if(root.right!=null){
            helper(new ArrayList(tempRes),root.right,target-root.val);
        }

    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值