华为OD机试真题——生成哈夫曼树(2025A卷:100分)Java/python/JavaScript/C/C++/GO六种最佳实现

在这里插入图片描述

2025 A卷 100分 题型

本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析;
并提供Java、python、JavaScript、C++、C语言、GO六种语言的最佳实现方式!

本文收录于专栏:《2025华为OD真题目录+全流程解析/备考攻略/经验分享》

华为OD机试真题《生成哈夫曼树》:


目录

    • 题目名称:生成哈夫曼树
      • 题目描述
    • Java
      • 问题分析
      • 解题思路
      • 代码实现
      • 代码详细解析
      • 示例测试
        • 输入1:
        • 输入2:
        • 输入3:
      • 综合分析
    • python
      • 问题分析
      • 解题思路
      • 代码实现
      • 代码详细解析
      • 示例测试
        • 输入1:
        • 输入2:
        • 输入3:
      • 综合分析
    • JavaScript
      • 问题分析
      • 解题思路
      • 代码实现
      • 代码详细解析
      • 示例测试
        • 示例1输入:
        • 示例2输入:
        • 示例3输入:
      • 综合分析
    • C++
      • 问题分析
      • 解题思路
      • 代码实现
      • 代码详细解析
      • 示例测试
        • 输入1:
        • 输入2:
        • 输入3:
      • 综合分析
    • C语言
      • 问题分析
      • 解题思路
      • 代码实现
      • 代码详细解析
      • 示例测试
        • 输入1:
        • 输入2:
        • 输入3:
      • 综合分析
    • GO
      • 问题分析
      • 解题思路
      • 代码实现
      • 代码详细解析
      • 示例测试
        • 示例1输入:
        • 示例2输入:
        • 示例3输入:
      • 综合分析


题目名称:生成哈夫曼树


  • 知识点:哈夫曼树、优先队列
  • 时间限制:1秒
  • 空间限制:256MB
  • 限定语言:不限

题目描述

给定长度为 n 的无序数字数组,每个数字代表二叉树的叶子节点权值(所有值 ≥ 1)。请根据输入生成哈夫曼树,并输出其中序遍历结果。要求满足以下限制条件:

  1. 节点权值规则:左节点权值 ≤ 右节点权值,根节点权值为左右子节点权值之和。
  2. 高度规则:若左右节点权值相同,左子树高度 ≤ 右子树高度。

输入描述

  • 第一行为整数 n(表示叶子节点数量,1 ≤ n ≤ 1e5)。
  • 第二行为 n 个正整数,表示每个叶子节点的权值。

输出描述

  • 输出中序遍历结果,数值间以空格分隔。若无有效树,返回空数组(用例保证输入有效)。

示例
输入:

5  
5 15 40 30 10  

输出:

40 100 30 60 15 30 5 15 10  

说明

  • 生成的哈夫曼树带权路径最短,如示例中总路径长度为:40×1 + 30×2 + 15×3 + 5×4 + 10×4 = 205。
  • 中序遍历结果需满足左节点权值 ≤ 右节点,且权值相同时左子树高度更低。

补充说明

  • 哈夫曼树构造需通过优先队列(小顶堆)合并最小权值节点,直至只剩一个根节点。
  • 时间复杂度需为 O(n log n),空间复杂度 O(n)。

Java

问题分析

我们需要根据给定的权值数组构建哈夫曼树,并输出其中序遍历结果。哈夫曼树的构建需要满足:

  1. 权值规则:左节点的权值 ≤ 右节点的权值。
  2. 高度规则:权值相同时,左子树的高度 ≤ 右子树的高度。
  3. 高效构造:使用优先队列(小顶堆)合并最小权值节点,时间复杂度为 O(n log n)。

解题思路

  1. 优先队列初始化:将每个权值初始化为叶子节点,按权值从小到大排列,权值相同时按高度从小到大排列。
  2. 构建哈夫曼树
    • 每次从队列取出两个最小节点,合并为新节点。
    • 新节点的权值为子节点之和,高度为较大子树高度加一。
    • 根据权值规则和高度规则确定左右子节点顺序。
  3. 中序遍历:使用非递归方式遍历树,按左 → 根 → 右顺序收集权值。

代码实现

import java.util.*;public class Main {static class Node {int weight;Node left;Node right;int height;// 叶子节点构造函数public Node(int weight) {this.weight = weight;this.height = 0; // 叶子节点高度为0}// 合并生成父节点的构造函数public Node(Node left, Node right) {this.left = left;this.right = right;this.weight = left.weight + right.weight;this.height = Math.max(left.height, right.height) + 1;}}public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();List<Integer> weights = new ArrayList<>();for (int i = 0; i < n; i++) {weights.add(scanner.nextInt());}// 优先队列:按权值从小到大,权值相同时按高度从小到大PriorityQueue<Node> queue = new PriorityQueue<>((a, b) -> {if (a.weight != b.weight) {return a.weight - b.weight;} else {return a.height - b.height;}});// 初始化队列,所有叶子节点入队for (int w : weights) {queue.add(new Node(w));}// 合并节点,构建哈夫曼树while (queue.size() > 1) {Node left = queue.poll();Node right = queue.poll();Node parent = new Node(left, right); // 自动满足左 ≤ 右queue.add(parent);}// 中序遍历Node root = queue.poll();List<Integer> result = new ArrayList<>();Deque<Node> stack = new LinkedList<>();Node current = root;// 非递归中序遍历while (current != null || !stack.isEmpty()) {while (current != null) {stack.push(current);current = current.left;}current = stack.pop();result.add(current.weight);current = current.right;}// 输出结果StringBuilder sb = new StringBuilder();for (int num : result) {sb.append(num).append(" ");}if (sb.length() > 0) {sb.deleteCharAt(sb.length() - 1);}System.out.println(sb);}
}

代码详细解析

  1. Node 类

    • weight:节点权值。
    • leftright:左右子节点。
    • height:节点高度,叶子节点为0,父节点为子节点最大高度加一。
  2. 优先队列初始化

    • 自定义比较器,先按权值排序,权值相同时按高度排序。
    • 将所有叶子节点加入队列。
  3. 合并节点

    • 循环取出两个最小节点,合并为新节点。
    • 新节点的左右顺序由队列比较器自动保证(权值小者优先,权值相同高度小者优先)。
  4. 中序遍历

    • 使用栈模拟递归,按左 → 根 → 右顺序遍历所有节点。
    • 收集所有节点的权值到结果列表。
  5. 输出处理

    • 将结果列表转换为字符串格式,确保末尾无空格。

示例测试

输入1:
5  
5 15 40 30 10  

输出

40 100 30 60 15 30 5 15 10  

解析:合并顺序确保所有条件满足,中序遍历结果正确。

输入2:
2  
3 5  

输出

3 8 5  

解析:合并生成父节点8,中序遍历顺序为3 → 8 → 5。

输入3:
1  
5  

输出

5  

解析:单个叶子节点,直接输出自身权值。


综合分析

  1. 时间复杂度:O(n log n)。
    • 优先队列的插入和删除操作均为 O(log n),共执行 O(n) 次。
  2. 空间复杂度:O(n)。
    • 存储哈夫曼树需要 O(n) 空间,优先队列和中序遍历栈均为 O(n)。
  3. 优势
    • 高效合并:优先队列确保每次合并选择最小权值节点。
    • 自动排序:比较器自动处理权值和高度规则,确保树结构正确。
  4. 适用场景:大规模数据处理,符合题目要求的 O(n log n) 时间复杂度和 O(n) 空间复杂度。

python

问题分析

我们需要根据给定的权值数组构建哈夫曼树,并输出其中序遍历结果。哈夫曼树的构建需满足:

  1. 权值规则:左节点权值 ≤ 右节点权值。
  2. 高度规则:权值相同时,左子树高度 ≤ 右子树高度。
  3. 高效构造:使用优先队列(小顶堆)合并最小节点,时间复杂度为 O(n log n)。

解题思路

  1. 优先队列初始化:将每个权值初始化为叶子节点,按权值从小到大排列,权值相同时按高度从小到大排列。
  2. 构建哈夫曼树
    • 每次从队列取出两个最小节点,合并为新节点。
    • 新节点的权值为子节点之和,高度为较大子树高度加一。
  3. 中序遍历:使用栈模拟递归遍历,按左 → 根 → 右顺序收集权值。

代码实现

import heapqclass Node:def __init__(self, weight, left=None, right=None):self.weight = weightself.left = leftself.right = right# 计算节点高度:叶子节点高度为0,父节点高度为子节点最大高度+1if left is None and right is None:self.height = 0else:self.height = max(left.height, right.height) + 1# 定义节点比较规则:先比权值,权值相同比高度def __lt__(self, other):if self.weight != other.weight:return self.weight < other.weightelse:return self.height < other.heightdef main():n = int(input())weights = list(map(int, input().split()))if n == 0:print("")return# 初始化优先队列heap = []for w in weights:heapq.heappush(heap, Node(w))# 合并节点直到只剩根节点while len(heap) > 1:left = heapq.heappop(heap)right = heapq.heappop(heap)# 创建父节点,自动满足左≤右的规则parent = Node(left.weight + right.weight, left, right)heapq.heappush(heap,

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

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

相关文章

房屋租赁系统 Java+Vue.js+SpringBoot,包括房屋类型、房屋信息、预约看房、合同信息、房屋报修、房屋评价、房主管理模块

房屋租赁系统 JavaVue.jsSpringBoot&#xff0c;包括房屋类型、房屋信息、预约看房、合同信息、房屋报修、房屋评价、房主管理模块 百度云盘链接&#xff1a;https://pan.baidu.com/s/1KmwOFzN9qogyaLQei3b6qw 密码&#xff1a;l2yn 摘 要 社会的发展和科学技术的进步&#xf…

Unity 中 Update、FixedUpdate 和 LateUpdate 的区别及使用场景

在Unity开发中,Update、FixedUpdate 和 LateUpdate 是生命周期函数中最常见也最容易混淆的一组。 一、调用时机 方法名调用频率调用时机说明Update()每帧调用一次跟随帧率(帧率高则调用频率高)FixedUpdate()固定时间间隔调用默认每 0.02 秒执行一次LateUpdate()每帧调用一次…

Docker镜像之windows系统

https://github.com/dockur/windows 在 Docker 容器中运行 Windows 功能 ISO 下载器KVM 加速基于网页的查看器 使用方法 启动容器并通过浏览器连接到端口 8006。整个安装过程将全自动完成&#xff0c;无需手动干预。当桌面界面出现时&#xff0c;表示 Windows 安装已完成&a…

C# 用户控件(User Control)详解:创建、使用与最佳实践

在C#应用程序开发中&#xff0c;用户控件&#xff08;User Control&#xff09;是一种强大的工具&#xff0c;它允许开发者将多个标准控件组合成一个可复用的自定义组件。无论是Windows Forms还是WPF&#xff0c;用户控件都能显著提高UI开发的效率&#xff0c;减少重复代码&…

pikachu靶场通关笔记09 XSS关卡05-DOM型XSS-X

目录 一、XSS 二、DOM型XSS 三、源码分析 1、打开DOM-X型XSS关卡 2、XSS探测 3、源码分析 四、渗透实战 1、Payload1 2、Payload2 3、Payload3 五、DOM型XSS与DOM-X型XSS区别 本系列为通过《pikachu靶场通关笔记》的XSS攻击关卡(共10关&#xff09;渗透集合&#xf…

湖北理元理律所:企业债务重组中的“法律缓冲带”设计

一、担保链危机的法律拆解技术 中小企业债务困局多源于担保链蔓延。本所处理某制造企业案例时&#xff0c;运用三层法律工具阻断风险传导&#xff1a; 1. 主合同审查 → 发现银行擅自变更借款用途 → 援引《民法典》第695条解除担保 2. 股东责任切割 → 证明企业财产独立 …

调整数据集的方法

我们对worldquant中的数据&#xff0c; 对数据频率怎么算 在 WorldQuant 平台中&#xff0c;数据更新频率是影响量化策略有效性、回测准确性和实盘交易表现的核心因素之一。它决定了数据的时效性和连续性&#xff0c;直接关系到策略能否捕捉市场动态、应对突发事件或适应不同…

[Linux] Linux 系统从启动到驱动加载

Linux 系统从启动到驱动加载 文章目录 Linux 系统从启动到驱动加载一、硬件上电与 BIOS/UEFI 阶段1. 1 硬件上电初始化1.2 BIOS/UEFI执行过程1.3 Bootloader加载细节 二、Bootloader 阶段三、Linux 内核初始化3.1 架构相关初始化&#xff08;setup_arch&#xff09;3.2 核心子系…

Spring Boot DevTools 热部署

在Spring Boot项目中加入 spring-boot-devtools 热部署依赖启动器后&#xff0c;通常不需要手动重启项目即可让更改生效。spring-boot-devtools 的核心特性之一就是自动重启或热加载。 Spring Boot DevTools 热部署关键知识点 &#x1f525; 目的&#xff1a;spring-boot-devt…

uni-app学习笔记十五-vue3页面生命周期(二)

onShow&#xff1a;用于监听页面显示&#xff0c;页面每次出现在屏幕上都触发&#xff0c;包括从下级页面点返回露出当前页面&#xff1b; onHide:监听页面隐藏&#xff0c;当离开当前页面时触发。 示例代码&#xff1a; <template><view>姓名&#xff1a;{{nam…

LIKE ‘%xxx%‘ 和 LIKE ‘xxx%‘ 的索引影响分析

LIKE ‘%xxx%’ 和 LIKE ‘xxx%’ 的索引影响分析 一、基础概念解析 1.1 LIKE操作符的工作原理 LIKE是SQL中用于模式匹配的操作符,支持两种通配符: %:匹配任意数量字符(包括零个字符)_:匹配单个字符go专栏:https://duoke360.com/tutorial/path/golang 1.2 数据库索引…

【软件测试】测试框架(unittest/pytest)

本文介绍了Python 中最常用的两个测试框架&#xff1a;unittest 和 pytest&#xff0c;帮助你编写更规范、可维护的自动化测试用例。 一、unittest 框架 unittest 是 Python 内置的标准库&#xff0c;无需额外安装&#xff0c;适合初学者入门。它借鉴了 JUnit 的设计理念&…

麒麟信安安装谷歌浏览器

参考文档 麒麟信安系统Chrome离线安装包&#xff1a;高效便捷的浏览器解决方案-CSDN博客 项目文件预览 - 麒麟信安系统Chrome离线安装包:本仓库提供了一个适用于麒麟信安系统的Chrome浏览器离线安装包。该安装包包含了所有必要的依赖文件&#xff0c;并且已经对系统中已有的依…

Wireshark 使用教程:让抓包不再神秘

一、什么是 tshark&#xff1f; tshark 是 Wireshark 的命令行版本&#xff0c;支持几乎所有 Wireshark 的核心功能。它可以用来&#xff1a; 抓包并保存为 pcap 文件 实时显示数据包信息 提取指定字段进行分析 配合 shell 脚本完成自动化任务 二、安装与验证 Kali Linux…

从0到1:多医院陪诊小程序开发笔记(上)

概要设计 医院陪诊预约小程序&#xff1a;随着移动互联网的普及&#xff0c;越来越多的医院陪诊服务开始向线上转型, 传统的预约方式往往效率低下&#xff0c;用户需耗费大量时间进行电话预约或现场排队&#xff0c;陪诊服务预约小程序集多种服务于一体&#xff0c;可以提高服…

定时任务:springboot集成xxl-job-core(二)

定时任务实现方式&#xff1a; 存在的问题&#xff1a; xxl-job的原理&#xff1a; 可以根据服务器的个数进行动态分片&#xff0c;每台服务器分到的处理数据是不一样的。 1. 多台机器动态注册 多台机器同时配置了调度器xxl-job-admin之后&#xff0c;执行器那里会有多个注…

Unity使用Lua框架和C#框架开发游戏的区别

在Unity中使用Lua框架和C#框架开发游戏有显著的区别&#xff0c;主要体现在性能、开发效率、热更新能力、维护成本等方面。 1. 语言类型与设计目标 维度LuaC#类型动态类型、解释型脚本语言静态类型、编译型面向对象语言设计初衷轻量级嵌入、配置和扩展宿主程序通用开发&#…

高精度文档解析利器:Mistral OCR 全面解析与技术应用

目录 &#x1f680; 高精度文档解析利器&#xff1a;Mistral OCR 全面解析与技术应用 一、什么是 Mistral OCR&#xff1f; 二、Mistral OCR 的核心特点 ✅ 1. 支持复杂文档结构解析 ✅ 2. 高识别精度 ✅ 3. 与 AI 系统深度集成 ✅ 4. 可扩展性与容错能力 三、技术原理…

腾讯云开发者社区文章内容提取免费API接口教程

接口简介&#xff1a; 提取指定腾讯云开发者社区文章内容。本接口仅做内容提取&#xff0c;未经作者授权请勿转载。 请求地址&#xff1a; https://cn.apihz.cn/api/caiji/tencent.php 请求方式&#xff1a; POST或GET。 请求参数&#xff1a; 【名称】【参数】【必填】【说…

【项目】在线OJ(负载均衡式)

目录 一、项目目标 二、开发环境 1.技术栈 2.开发环境 三、项目树 目录结构 功能逻辑 编写思路 四、编码 1.complie_server 服务功能 代码蓝图 开发编译功能 日志功能 ​编辑 测试编译模块 开发运行功能 设置运行限制 jsoncpp 编写CR 如何生成唯一文件名 …