题目描述
给满出二叉树,编写算法将其转化为求和树
什么是求和树:二叉树的求和树, 是一颗同样结构的二叉树,其树中的每个节点将包含原始树中的左子树和右子树的和。
二叉树:
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
题解:这题思路不难想到,就是写代码的时候要注意一些细节,还有一点就是测试数据中有不是满二叉树的情况。
#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
int tree[N], res[N], mark[N];
vector<int> foo, bar;
void read(vector<int> &vec){
int num = 0, sg = 1;
char c;
while((c = getchar()) != '\n'){
if(c != ' '){
if(c != '-'){
num = num * 10 + (c - '0');
} else {
sg = -1;
}
} else {
vec.push_back(num * sg);
num = 0;
sg = 1;
}
}
vec.push_back(num * sg);
}
void ask(int index, int lf, int rf, int lb, int rb){
if(lf > rf || lb > rb){
return;
}
int llen, need;
tree[index] = foo[lf];
mark[index] = 0;
for (int i = lb; i <= rb; i++){
if(bar[i] == foo[lf]){
need = i;
break;
}
}
llen = need - lb;
ask(index * 2, lf + 1, lf + llen, lb, rb + llen - 1);
ask(index * 2 + 1, lf + llen + 1, rf, need + 1, rb);
}
void print(int index){
if(mark[index] == -1){
return;
}
print(index * 2);
cout << res[index] << " ";
print(index * 2 + 1);
}
int main(){
read(foo);
read(bar);
memset(mark, -1, sizeof(mark));
int len, depth;
len = foo.size() - 1;
depth = (int)log2(len + 1) + 1;
ask(1, 0, len, 0, len);
for (int i = depth; i >= 1; i--){
int start = (1 << i);
for (int j = 0, k = start; j < start / 2; j++, k += 2){
res[k / 2] = res[k] + res[k + 1];
if(mark[k] != -1){
res[k / 2] += tree[k];
}
if(mark[k + 1] != -1){
res[k / 2] += tree[k + 1];
}
}
}
print(1);
return 0;
}