2019校招真题在线编程 将满二叉树转换为求和树

题目描述

给满出二叉树,编写算法将其转化为求和树

什么是求和树:二叉树的求和树, 是一颗同样结构的二叉树,其树中的每个节点将包含原始树中的左子树和右子树的和。

二叉树:
                  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;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值