牛客题解 | 将满二叉树转换为求和树

news/2025/3/5 10:05:01/文章来源:https://www.cnblogs.com/wc529065/p/18752049

题目

题目链接

求和树转换算法

解题思路

  1. 基本步骤:

    • 根据前序和中序遍历重建原始二叉树
    • 将原始二叉树转换为求和树
    • 输出求和树的中序遍历
  2. 关键点:

    • 满二叉树的特点:每个非叶子节点都有两个子节点
    • 求和树节点值 = 左子树所有节点值之和 + 右子树所有节点值之和
    • 叶子节点的求和树值为0

代码实现

#include <iostream>
#include <vector>
#include <string>
#include <sstream>
using namespace std;// 树节点定义
struct TreeNode {int val;TreeNode* left;TreeNode* right;TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};// 构建二叉树
TreeNode* buildTree(vector<int>& preorder, int preStart, int preEnd,vector<int>& inorder, int inStart, int inEnd) {if (preStart > preEnd) return NULL;TreeNode* root = new TreeNode(preorder[preStart]);// 在中序遍历中找根节点位置int rootIndex = inStart;for (int i = inStart; i <= inEnd; i++) {if (inorder[i] == preorder[preStart]) {rootIndex = i;break;}}int leftSubtreeSize = rootIndex - inStart;// 递归构建左右子树root->left = buildTree(preorder, preStart + 1, preStart + leftSubtreeSize,inorder, inStart, rootIndex - 1);root->right = buildTree(preorder, preStart + leftSubtreeSize + 1, preEnd,inorder, rootIndex + 1, inEnd);return root;
}// 转换为求和树
int convertToSumTree(TreeNode* root) {if (root == NULL) return 0;int oldValue = root->val;// 递归计算左右子树的和int leftSum = convertToSumTree(root->left);int rightSum = convertToSumTree(root->right);// 更新当前节点的值为左右子树的和root->val = leftSum + rightSum;// 返回包含当前节点的子树所有节点值的和return oldValue + leftSum + rightSum;
}// 中序遍历
void inorderTraversal(TreeNode* root, vector<int>& result) {if (root == NULL) return;inorderTraversal(root->left, result);result.push_back(root->val);inorderTraversal(root->right, result);
}int main() {string line;// 读取前序遍历getline(cin, line);istringstream iss1(line);vector<int> preorder;int num;while (iss1 >> num) {preorder.push_back(num);}// 读取中序遍历getline(cin, line);istringstream iss2(line);vector<int> inorder;while (iss2 >> num) {inorder.push_back(num);}// 构建二叉树TreeNode* root = buildTree(preorder, 0, preorder.size() - 1,inorder, 0, inorder.size() - 1);// 转换为求和树convertToSumTree(root);// 获取求和树的中序遍历vector<int> result;inorderTraversal(root, result);// 输出结果for (int i = 0; i < result.size(); i++) {cout << result[i];if (i < result.size() - 1) cout << " ";}cout << endl;return 0;
}
import java.util.*;public class Main {static class TreeNode {int val;TreeNode left;TreeNode right;TreeNode(int val) {this.val = val;}}public static void main(String[] args) {Scanner sc = new Scanner(System.in);// 读取前序遍历String[] preStr = sc.nextLine().split(" ");int[] preorder = new int[preStr.length];for(int i = 0; i < preStr.length; i++) {preorder[i] = Integer.parseInt(preStr[i]);}// 读取中序遍历String[] inStr = sc.nextLine().split(" ");int[] inorder = new int[inStr.length];for(int i = 0; i < inStr.length; i++) {inorder[i] = Integer.parseInt(inStr[i]);}// 重建二叉树TreeNode root = buildTree(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);// 转换为求和树convertToSumTree(root);// 输出求和树的中序遍历List<Integer> result = new ArrayList<>();inorderTraversal(root, result);// 打印结果for(int i = 0; i < result.size(); i++) {System.out.print(result.get(i));if(i < result.size() - 1) {System.out.print(" ");}}}// 构建二叉树private static TreeNode buildTree(int[] preorder, int preStart, int preEnd,int[] inorder, int inStart, int inEnd) {if(preStart > preEnd) return null;TreeNode root = new TreeNode(preorder[preStart]);// 在中序遍历中找到根节点位置int rootIndex = 0;for(int i = inStart; i <= inEnd; i++) {if(inorder[i] == preorder[preStart]) {rootIndex = i;break;}}int leftSubtreeSize = rootIndex - inStart;// 递归构建左右子树root.left = buildTree(preorder, preStart + 1, preStart + leftSubtreeSize,inorder, inStart, rootIndex - 1);root.right = buildTree(preorder, preStart + leftSubtreeSize + 1, preEnd,inorder, rootIndex + 1, inEnd);return root;}// 转换为求和树private static int convertToSumTree(TreeNode root) {if(root == null) return 0;// 获取原始值int oldValue = root.val;// 递归计算左右子树的和int leftSum = convertToSumTree(root.left);int rightSum = convertToSumTree(root.right);// 更新当前节点的值为左右子树的和root.val = leftSum + rightSum;// 返回包含当前节点的子树所有节点值的和return oldValue + leftSum + rightSum;}// 中序遍历private static void inorderTraversal(TreeNode root, List<Integer> result) {if(root == null) return;inorderTraversal(root.left, result);result.add(root.val);inorderTraversal(root.right, result);}
}
class TreeNode:def __init__(self, val=0):self.val = valself.left = Noneself.right = Nonedef buildTree(preorder, preStart, preEnd, inorder, inStart, inEnd):if preStart > preEnd:return None# 创建根节点root = TreeNode(preorder[preStart])# 在中序遍历中找到根节点位置rootIndex = inStartfor i in range(inStart, inEnd + 1):if inorder[i] == preorder[preStart]:rootIndex = ibreakleftSubtreeSize = rootIndex - inStart# 递归构建左右子树root.left = buildTree(preorder, preStart + 1, preStart + leftSubtreeSize,inorder, inStart, rootIndex - 1)root.right = buildTree(preorder, preStart + leftSubtreeSize + 1, preEnd,inorder, rootIndex + 1, inEnd)return rootdef convertToSumTree(root):if not root:return 0# 保存原始值oldValue = root.val# 递归计算左右子树的和leftSum = convertToSumTree(root.left)rightSum = convertToSumTree(root.right)# 更新当前节点的值为左右子树的和root.val = leftSum + rightSum# 返回包含当前节点的子树所有节点值的和return oldValue + leftSum + rightSumdef inorderTraversal(root, result):if not root:returninorderTraversal(root.left, result)result.append(root.val)inorderTraversal(root.right, result)def solve():# 读取输入preorder = list(map(int, input().split()))inorder = list(map(int, input().split()))# 构建二叉树root = buildTree(preorder, 0, len(preorder) - 1,inorder, 0, len(inorder) - 1)# 转换为求和树convertToSumTree(root)# 获取求和树的中序遍历result = []inorderTraversal(root, result)# 输出结果print(' '.join(map(str, result)))if __name__ == "__main__":solve()

算法分析

  1. 时间复杂度:

    • 构建二叉树:\(\mathcal{O}(n^2)\)
    • 转换为求和树:\(\mathcal{O}(n)\)
    • 总体:\(\mathcal{O}(n^2)\)
  2. 空间复杂度:

    • 递归调用栈:\(\mathcal{O}(h)\)\(h\)为树高
    • 存储结果:\(\mathcal{O}(n)\)
    • 总体:\(\mathcal{O}(n)\)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/893896.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI制作

首先,我们需要设计数据库表结构。根据需求,我们需要两个表:仓库表和物资台账明细表。1.1 仓库表 (warehouse) 字段名 数据类型 描述 warehouse_id VARCHAR(10) 仓库编号(唯一) name VARCHAR(50) 仓库名称 location VARCHAR(100) 仓库位置 capacity INT 仓库容量 created_a…

为应用程序分配单个Sharepoint站点的权限

最近工作需要在Sharepoint Online上建立一个站点用于信息同步。另一个租户下有一个站点的信息将需要同步到这个新站点中。 为此,我们需要新建一个应用程序用于数据同步。这个可以在Microsoft Entra admin center中完成。找到Applications--App registrations在这里新建一个应用…

花3分钟来了解一下Vue3中的插槽到底是什么玩意

前言 插槽看着是一个比较神秘的东西,特别是作用域插槽还能让我们在父组件里面直接访问子组件里面的数据,这让插槽变得更加神秘了。其实Vue3的插槽远比你想象的简单,这篇文章我们来揭开插槽的神秘面纱。 欧阳也在找工作,坐标成都求内推! 看个demo 我们先来看个常见的插槽de…

OKR 推行五大注意事项

OKR(目标与关键成果法)是一种高效的目标管理工具,但在推行过程中往往会面临诸多挑战。以下是OKR推行的五大难点,以及在推行过程中需要注意的五个关键事项,并结合Tita平台的特点进行简要介绍。OKR推行的五大难点目标设定不合理确定清晰、合理且可衡量的目标和关键成果是推行…

注册用户同步没有了

解决: https://vip.kingdee.com/knowledge/642363720735104256?productLineId=1&isKnowledge=2&lang=zh-CN

同步注册用户没有了

解决: https://vip.kingdee.com/knowledge/642363720735104256?productLineId=1&isKnowledge=2&lang=zh-CN

2025.03.04 CW 模拟赛 D. 积木

D. 积木 和之前容斥专题的一道题有点像. 思路 注意到虽然 \(1 \le n, m \le 50\), 但是 * 的个数不超过 12 个. 于是我们可以考虑对 * 的个数进行状压, 也就是钦定哪些 * 必须作为积木的中心 \((\)下文统称为 o\()\). 钦定完成, 我们考虑什么情况下是不合法的. 如下图, 这两种情…

9.0版本要求使用https登录管理中心

解决:如下图 https://vip.kingdee.com/knowledge/552811796516494592?productLineId=1&isKnowledge=2&lang=zh-CN

西门子 smart 700 人机界面 HMI erwa.cn二娃备忘

情况是这样,触摸屏型号为smart 700IE,以前的程序已经确定丢失了,已经是两年前其他人搞的程序了。目前想要将此smart 700IE触摸屏程序得出来,该怎么实现,请详细告知,非常感谢 最佳答案 Smart Panels 均不支持“回传”功能,只支持“备份”“恢复”功能。 那“回传”与“…

文件同步备份软件,让文件同步更安全更稳定!

在数字化时代,数据已然成为企业的核心资产,而确保服务器之间文件的高效同步,是保障数据一致性、维持业务连续性的关键所在。无论是大型企业构建多数据中心的复杂架构,还是分布式系统力求各节点数据的统一,文件同步备份软件都发挥着无可替代的作用。它就像是企业数据流转的…

无法加载kingdee k3 cloud erp V7.2的许可文件,许可文件可能被篡改,请联系管理员

原因:如下图,正式补丁在安装时出现了异常导致。 解决:重新安装正式补丁以及临时补丁。

2025年最火爆的5款跨网文件安全交换系统优缺点对比

跨网文件安全交换系统主要用于在不同网络环境间安全传输文件,确保数据的机密性、完整性和可用性。 能解决跨网文件传输的方式有很多,比如FTP/FTPS、SFTP、云存储服务、P2P文件共享以及Ftrans Ferry跨网文件安全交换系统各有优缺点。以下是它们的详细对比: 一、FTP/FTPS优点:…