将满二叉树转换为求和树
在网上看到一个道题目觉的有些意思分享给大家。
题目
/**
* 给满出二叉树,编写算法将其转化为求和树
*
* 什么是求和树:二叉树的求和树, 是一颗同样结构的二叉树,其树中的每个节点将包含原始树中的左子树和右子树的和。
*
* 二叉树:
* 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;
}
}