将满二叉树转换为求和树

 

将满二叉树转换为求和树

 

在网上看到一个道题目觉的有些意思分享给大家。

题目

/**
 * 给满出二叉树,编写算法将其转化为求和树
 *
 * 什么是求和树:二叉树的求和树, 是一颗同样结构的二叉树,其树中的每个节点将包含原始树中的左子树和右子树的和。
 *
 * 二叉树:
 *                   10
 *                /      \
 *              -2        6
 *            /   \      /  \
 *           8    -4    7    5
 *
 * 求和树:
 *                  20(4-2+12+6)
 *                /      \
 *            4(8-4)      12(7+5)
 *             /   \      /  \
 *           0      0    0    0
 *
 * 二叉树给出前序和中序输入,求和树要求中序输出;
 * 所有处理数据不会大于int;
 *
 * 输入描述:
 * 2行整数,第1行表示二叉树的前序遍历,第2行表示二叉树的中序遍历,以空格分割
 * 输出描述:
 * 1行整数,表示求和树的中序遍历,以空格分割
 * 示例1
 * 输入
 * 复制
 * 10 -2 8 -4 6 7 5
 * 8 -2 -4 10 7 6 5
 * 输出
 * 复制
 * 0 4 0 20 0 12 0
 */





思路

结果要求是求和中序,那么首先将中序的结果数组(int[] result)先建立起来,这个“结果数组”肯定和输入的中序字符串的顺序是一样的,只需要将数组中的每个元素填充即可。

如何填充每个元素?

就是将原中序元素下的左右子树元素值都加起来放到该位置上,也就是将以“原中序元素”为根的整颗二叉树元素相加再减去根元素的值。比如根据前序字符串"10 -2 8 -4 6 7 5"的第一个数字“10”和中序字符串 "8 -2 -4 10 7 6 5"中的“10”在第4个位置就可知道“结果数组”中的第4个位置的值为 (10 -2 + 8 - 4 + 6 + 7 + 5 )- 10 = 20;

代码

/**
 * 给满出二叉树,编写算法将其转化为求和树
 *
 * 什么是求和树:二叉树的求和树, 是一颗同样结构的二叉树,其树中的每个节点将包含原始树中的左子树和右子树的和。
 *
 * 二叉树:
 *                   10
 *                /      \
 *              -2        6
 *            /   \      /  \
 *           8    -4    7    5
 *
 * 求和树:
 *                  20(4-2+12+6)
 *                /      \
 *            4(8-4)      12(7+5)
 *             /   \      /  \
 *           0      0    0    0
 *
 * 二叉树给出前序和中序输入,求和树要求中序输出;
 * 所有处理数据不会大于int;
 *
 * 输入描述:
 * 2行整数,第1行表示二叉树的前序遍历,第2行表示二叉树的中序遍历,以空格分割
 * 输出描述:
 * 1行整数,表示求和树的中序遍历,以空格分割
 * 示例1
 * 输入
 * 复制
 * 10 -2 8 -4 6 7 5
 * 8 -2 -4 10 7 6 5
 * 输出
 * 复制
 * 0 4 0 20 0 12 0
 * @Author: hu
 * @Date: 2020-04-17 18:45
 */
public class TreeTestMain {

    public static void main (String[] args) {

        TreeTestMain main = new TreeTestMain();
        //不用建立二叉树,直接根据前序和中序推断出左右子树,然后按照中序的顺序打印即可
        main.outInTreeResult("10 -2 8 -4 6 7 5", "8 -2 -4 10 7 6 5");
        //System.out.println("---");//0 4 0 20 0 12 0
    }

    /**
     * 输入两行前序和中序的字符串,打印求和树的中序遍历
     * @param preStr
     * @param inStr
     */
    public void outInTreeResult(String preStr, String inStr) {
        int[] pre = getIntArr(preStr);
        int[] in = getIntArr(inStr);
        int[] result = new int[pre.length];
        setResultIntArr(pre, in, in, result);

        for(int paramInt : result) {
            System.out.print(paramInt + " ");
        }

    }
    private void setResultIntArr(int[] pre, int[] in, int[] originIn, int[] result) {
        if(pre.length == 0 && in.length == 0 ) {
            return;
        }
        int rootNum = pre[0];
        int sum = 0;
        for(int i = 0; i < in.length; i++) {
            sum += in[i];
        }
        sum -= rootNum;
        for(int i = 0; i < originIn.length; i++) {
            if(rootNum == originIn[i]) {
                result[i] = sum;
                break;
            }
        }
        if(in.length == 1) {
          return;
        }
        TreeArr childIn = getInTreeArr(rootNum , in);
        if(childIn != null) {
            int[] inLeft = childIn.left;
            TreeArr childPre = getPreTreeArr(inLeft.length , pre);
            setResultIntArr(childPre.left, inLeft, originIn, result);
            setResultIntArr(childPre.right, childIn.right, originIn, result);
        }
    }
    private TreeArr getPreTreeArr(int inLeftLength , int[] pre) {
        if(pre.length == 0) {
            return null;
        }
        int[] leftArr = new int[inLeftLength];
        int[] rightArr = new int[pre.length - 1 -inLeftLength];
        for(int i = 1; i < pre.length; i++) {
            if(i <= inLeftLength) {
                leftArr[i-1] = pre[i];
            } else{
                rightArr[i - inLeftLength - 1] = pre[i];
            }
        }
        return new TreeArr(leftArr, rightArr);
    }
    private TreeArr getInTreeArr(int rootNum , int[] in) {
        if(in.length == 0) {
            return null;
        }
        int rootPosition = -1;
        for(int i = 0; i < in.length; i++) {
            if(rootNum == in[i]) {
                rootPosition = i;
                break;
            }
        }
        int[] leftArr = new int[rootPosition];
        int[] rightArr = new int[in.length - 1 -rootPosition];
        for(int i = 0; i < in.length; i++) {
            if(i < rootPosition) {
                leftArr[i] = in[i];
            } else if(i > rootPosition){
                rightArr[i-rootPosition-1] = in[i];
            }
        }
        return new TreeArr(leftArr, rightArr);
    }

    /**
     * 将字符串转为int数组
     * @param str
     * @return
     */
    private int[] getIntArr(String str) {
        String[] arr = str.split(" ");
        int[] intArr = new int[arr.length];
        for(int i = 0; i < arr.length; i++) {
            intArr[i] = Integer.parseInt(arr[i]);
        }
        return intArr;
    }

    private class TreeArr {
        TreeArr(int[] left, int[] right) {
            this.left = left;
            this.right = right;
        }
        int[] left;
        int[] right;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值