二叉树计算 - 华为OD统一考试

OD统一考试(C卷)

分值: 200分

题解: Java / Python / C++

alt

题目描述

给出一个二叉树如下图所示:
6
/ \
7 9
\ /
-2 6

请由该二叉树生成一个新的二叉树,它满足其树中的每个节点将包含原始树中的左子树和右子树的和。

​ 20(7-2+9+6)
​ / \
​ -2 6
​ \ /

​ 0 0

左子树表示该节点左侧叶子节点为根节点的一颗新树;右子树表示该节点右侧叶子节点为根节点的一颗新树

输入描述

2行整数,第1行表示二叉树的中序遍历,第2行表示二叉树的前序遍历,以空格分割

例如:

7 -2 6 6 9
6 7 -2 9 6

输出描述

1行整数,表示求和树的中序遍历,以空格分割

例如:

输出1
-2 0 20 0 6

示例1

输入:
-3 12 6 8 9 -10 -7
8 12 -3 6 -10 9 -7

输出:
0 3 0 7 0 2 0

题解

递归的题目

根据树的中序和先序遍历可以唯一确定一颗树,题解中将中序和先序字符串看成一个整体(树)。

题目求的是求和树的中序遍历, 因此还是使用递归中序遍历的方式去遍历树,遍历的同时去求 左右子树和(即为答案)。

Java

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
import java.util.stream.Collectors;

/**
 * @author code5bug
 */
public class Main {
   
    static List<Integer> rs = new ArrayList<>();

    public static void main(String[] args) {
   
        Scanner scanner = new Scanner(System.in);

        // 中序遍历
        List<Integer> inorder = Arrays.stream(scanner.nextLine().split(" "))
                .map(p -> Integer.parseInt(p)).collect(Collectors.toList());
        // 先序遍历
        List<Integer> preorder = Arrays.stream(scanner.nextLine().split(" "))
                .map(p -> Integer.parseInt(p)).collect(Collectors.toList());

        solve(inorder, preorder);

        for (int num : rs) {
   
            System.out.print(num + " ");
        }
    }

    static void solve(List<Integer> inorder, List<Integer> preorder) {
   
        if (inorder.isEmpty() || preorder.isEmpty()) {
   
            return;
        }

        // 数根节点的值
        int rootVal = preorder.get(0);
        int idx = inorder.indexOf(rootVal);

        // 中序,左右子树
        List<Integer> leftInorder = inorder.subList(0, idx);
        List<Integer> rightInorder = inorder.subList(idx + 1, inorder.size());

        // 先序,左右子树
        List<Integer> leftPreorder = preorder.subList(1, idx + 1);
        List<Integer> rightPreorder = preorder.subList(idx + 1, preorder.size());

        solve(leftInorder, leftPreorder);

        // 左右子树求值求和
        int leftSum = leftInorder.stream().reduce(0, Integer::sum);
        int rightSum = rightInorder.stream().reduce(0, Integer::sum);
        rs.add(leftSum + rightSum);

        solve(rightInorder, rightPreorder);
    }

}

Python

# 以下 2 行代码解决递归深度报错只能 AC 95% 的问题
import sys
sys.setrecursionlimit(10000)

# 中序遍历
inorder = list(map(int, input().split()))
# 先序遍历
preorder = list(map(int, input().split()))

# 求和树的中序遍历
rs = []

def solve(inorder, preorder):
    if not inorder or not preorder:
        return
    
    root_val = preorder[0]
    idx = inorder.index(root_val)

    left_inorder = inorder[: idx]
    right_inorder = inorder[idx + 1:]

    left_preorder = preorder[1: idx + 1]
    right_preorder = preorder[idx + 1:]

    solve(left_inorder, left_preorder)
    rs.append(sum(left_inorder) + sum(right_inorder))
    solve(right_inorder, right_preorder)

solve(inorder, preorder)
print(*rs)

C++

#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>

using namespace std;

vector<int> rs;

void solve(vector<int>& inorder, vector<int>& preorder) {
   
    if (inorder.empty() || preorder.empty()) {
   
        return;
    }

    // 数根节点的值
    int rootVal = preorder[0];
    auto it = find(inorder.begin(), inorder.end(), rootVal);
    int idx = distance(inorder.begin(), it);

    // 中序,左右子树
    vector<int> leftInorder(inorder.begin(), inorder.begin() + idx);
    vector<int> rightInorder(inorder.begin() + idx + 1, inorder.end());

    // 先序,左右子树
    vector<int> leftPreorder(preorder.begin() + 1, preorder.begin() + idx + 1);
    vector<int> rightPreorder(preorder.begin() + idx + 1, preorder.end());

    solve(leftInorder, leftPreorder);

    // 左右子树求值求和
    int leftSum = accumulate(leftInorder.begin(), leftInorder.end(), 0);
    int rightSum = accumulate(rightInorder.begin(), rightInorder.end(), 0);
    rs.push_back(leftSum + rightSum);

    solve(rightInorder, rightPreorder);
}

vector<int> read_line(vector<int>& collect) {
   
    int v;
    while (cin >> v) {
   
        collect.push_back(v);
        if (cin.peek() == '\n') break;
    }
    return collect;
}

int main() {
   
    // 中序遍历
    vector<int> inorder;
    read_line(inorder);

    // 先序遍历
    vector<int> preorder;
    read_line(preorder);

    solve(inorder, preorder);

    for (int num : rs) {
   
        cout << num << " ";
    }

    return 0;
}

相关练习题

题号 题目 难易
LeetCode 105 105. 从前序与中序遍历序列构造二叉树 中等
LeetCode 106 106. 从中序与后序遍历序列构造二叉树 中等

‍❤️‍华为OD机试面试交流群每日真题分享): 加V时备注“华为od加群”

🙏整理题解不易, 如果有帮助到您,请给点个赞 ‍❤️‍ 和收藏 ⭐,让更多的人看到。🙏🙏🙏

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-01-28 12:42:01       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-01-28 12:42:01       100 阅读
  3. 在Django里面运行非项目文件

    2024-01-28 12:42:01       82 阅读
  4. Python语言-面向对象

    2024-01-28 12:42:01       91 阅读

热门阅读

  1. 2023华为od机试C卷【跳马问题】C语言 实现

    2024-01-28 12:42:01       47 阅读
  2. 【算法题】72. 编辑距离

    2024-01-28 12:42:01       42 阅读
  3. LLVM编译器的结构

    2024-01-28 12:42:01       53 阅读
  4. 计算机网络概述及 参考模型

    2024-01-28 12:42:01       57 阅读
  5. 关于CMAKE构建C/C++遇到的问题汇总

    2024-01-28 12:42:01       60 阅读
  6. 栈的基础知识

    2024-01-28 12:42:01       50 阅读
  7. perl 通过信号控制执行超时

    2024-01-28 12:42:01       56 阅读
  8. 设计模式 :总结篇

    2024-01-28 12:42:01       62 阅读
  9. Spring Cloud Sleuth与Zipkin详解

    2024-01-28 12:42:01       67 阅读