[编程题]关于二叉树的路径

题目:

给定一颗二叉树,其中每个结点都含有一个数值。设计一个算法,打印结点数值总和等于某个给定值的所有路径。注意,路径不一定非得从二叉树的根节点或叶子节点开始或结束。

题目看起来似乎有点复杂,那么我们先简化一下,若路径从根节点开始,在任意节点结束。
于是就可以从根节点开始,向左向右访问子节点,计算每条路径上根节点到当前节点的数值和。若与给定的值相同变打印当前路径。
注意:

  • 就算找到了总和,仍需要继续访问这条路径。
  • 不必重复计算根节点到每个节点的和,可以用一个数据结构存储和。

那么从任意路径开始怎么办呢?可以把问题转化为“这个节点为某条路径的末端,这条路径的和为给定的数值”。
递归访问每个节点n时,将根节点到n的完整路径传入函数,再以相反的顺序将n到根节点的子路径的值加起来,等于给定的值时就打印路径。

public void findSum(TreeNode node, int sum){
    int depth = depth(node);
    int[] path = new int[depth];
    findSum(node, sum, path, 0);
}

public void findSum(TreeNode node, int sum, int[] path, int level){
    if(node == null){
        return;
    }
    path[level] = node.data; //将当前节点插入路径
    int pathSum = 0;
    for(int i = level; i <= 0; i--){
        pathSum += path[i];
        if(pathSum == sum){
            print(path, i, level);
        }
    }
    findSum(node.left, sum, path, level + 1);
    findSum(node.right, sum, path, level + 2);
    path[level] = Integer.MIN_VALUE; //只是个编程习惯,将当前节点从路径中移除。其实下次会覆盖这个节点。
}

public int depth(TreeNode node){
    if(node == null){
        return 0;
    }
    return 1 + Math.max(depth(node.left), depth(node.right));
}

public void print(int[] path, int start, int end){
    for(int i = start; i <= end; i++){
        System.out.print(path[i] + " ");
    }
    System.out.println();
}


好了,如果题目再变一下:

有一棵二叉树,树上每个点标有权值,权值各不相同,请设计一个算法算出权值最大的叶节点到权值最小的叶节点的距离。二叉树每条边的距离为1,一个节点经过多少条边到达另一个节点为这两个节点之间的距离。
给定二叉树的根节点root,请返回所求距离。

先遍历全部树,记录下最小值和最大值的值和位置,再根据位置来算出距离。

public class Tree {
    private int max=0; //记录最大值
    private int min=99999; //记录最小值
    private StringBuilder maxcodec; //记录最大值的记录 0表示向左边;1表示右边
    private StringBuilder mincodec; //记录最小值的记录

    void PreOrder(TreeNode T,char code,StringBuilder codec){
        if(T!=null){           
            codec.append(code);
            if(T.left==null && T.right==null)
            {
                if(max<T.val)
                {
                    max=T.val;
                    maxcodec = codec;
                }

                if(min>T.val)
                {
                    min=T.val;
                    mincodec = codec;
                }
            }
            PreOrder(T.left,'0',new StringBuilder(codec));
            PreOrder(T.right,'1',new StringBuilder(codec));
        }
    }
    public int getDis(TreeNode root) {
        PreOrder(root,'0',new StringBuilder());
        int index=0;
        int length = maxcodec.length()>mincodec.length()?maxcodec.length():mincodec.length();
        for(index=0; index<length ;index++)
        {
            if(maxcodec.charAt(index)!=mincodec.charAt(index))
                break;
        }
        return (maxcodec.substring(index).length()+mincodec.substring(index).length());

    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值