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

article/2025/6/23 19:33:05

在这里插入图片描述

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.hkcw.cn/article/fKRIrvocTn.shtml

相关文章

Python实现P-PSO优化算法优化BP神经网络分类模型项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档&#xff09;&#xff0c;如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 随着人工智能技术的快速发展&#xff0c;神经网络在分类任务中展现了强大的性能。BP&#xff08;Back Propagation&…

学习海康VisionMaster之表面缺陷滤波

一&#xff1a;进一步学习了 今天学习下VisionMaster中的表面缺陷滤波&#xff1a;简单、无纹理背景的表面缺陷检测&#xff0c;可以检测表面的异物&#xff0c;缺陷&#xff0c;划伤等 二&#xff1a;开始学习 1&#xff1a;什么表面缺陷滤波&#xff1f; 表面缺陷滤波的核心…

34.x64汇编写法(一)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 上一个内容&#xff1a;33.第二阶段x64游戏实战-InLineHook 首先打开 Visual Studio&#xff0c;然后创…

Java网络编程实战:TCP/UDP Socket通信详解与高并发服务器设计

&#x1f50d; 开发者资源导航 &#x1f50d;&#x1f3f7;️ 博客主页&#xff1a; 个人主页&#x1f4da; 专栏订阅&#xff1a; JavaEE全栈专栏 内容&#xff1a; socket(套接字)TCP和UDP差别UDP编程方法使用简单服务器实现 TCP编程方法Socket和ServerSocket之间的关系使用简…

算法:滑动窗口

1.长度最小的子数组 209. 长度最小的子数组 - 力扣&#xff08;LeetCode&#xff09; 运用滑动窗口&#xff08;同向双指针&#xff09;来解决&#xff0c;因为这些数字全是正整数&#xff0c;在left位置确定的下&#xff0c;right这个总sum会越大&#xff0c;所以我们先让num…

AI笔记 - 网络模型 - mobileNet

网络模型 mobileNet mobileNet V1网络结构深度可分离卷积空间可分![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/aff06377feac40b787cfc882be7c6e5d.png) 参考 mobileNet V1 网络结构 MobileNetV1可以理解为VGG中的标准卷积层换成深度可分离卷积 可分离卷积主要有…

新中地三维GIS开发智慧城市效果和应用场景

近年来&#xff0c;随着科技的发展和城市化进程的加速&#xff0c;智慧城市成为了全球各大城市的一个重要发展方向。 在这一背景下&#xff0c;三维GIS技术以其独特的优势&#xff0c;成为构建智慧城市不可或缺的工具。新中地GIS开发特训营正是在这样的大环境下应运而生&#…

Linux笔记---线程

1. 线程的介绍 1.1 线程的概念 基本定义&#xff1a; 线程&#xff08;Thread&#xff09;是操作系统能够进行运算调度的最小单位。它被包含在进程&#xff08;Process&#xff09;之中&#xff08;或者说是进程的一部分、对进程的划分&#xff09;&#xff0c;是进程中的实际…

Java数据结构之ArrayList(如果想知道Java中有关ArrayList的知识点,那么只看这一篇就足够了!)

前言&#xff1a;ArrayList是Java中最常用的动态数组实现之一&#xff0c;它提供了便捷的操作接口和灵活的扩展能力&#xff0c;使得在处理动态数据集合时非常方便。本文将深入探讨Java中ArrayList的实现原理、常用操作以及一些使用场景。 一&#xff1a;体系结构 二&#xff…

antddesign使用iconfont的字体库和图标库

antddesign使用iconfont 使用iconfont自定义字体 1️⃣选择一种需要的字体&#xff0c;点击【字体包下载】&#xff1a; 2️⃣下载好的字体放到项目目录下&#xff1a;src/assets/fonts&#xff1a; 3️⃣新建styles/font.css文件&#xff1a; /* src/styles/fonts.css */ f…

LearnOpenGL-笔记-其十二

今天我们来将LearnOpenGL的高级光照部分彻底完结&#xff1a; Bloom 泛光是一个非常常见的用于改善图像质量的手段&#xff0c;其主要做法就是将某个高亮度区域的亮度向四周发善以实现该区域更亮的视觉效果&#xff08;因为显示器的亮度范围有限&#xff0c;需要通过泛光来体…

第十二节:第一部分:集合框架:概述、Collection集合的常用方法

集合体系结构 Collection集合体系 Collection的常用方法 代码&#xff1a; 代码一&#xff1a;认识Collection体系的特点 package com.itheima.day17_Collection;import java.util.ArrayList; import java.util.HashSet;/* * 目标:认识Collection体系的特点。 * */ public cl…

C++哈希表:unordered系列容器详解

本节目标 1.unordered系列关联式容器 2.底层结构 3.模拟实现 4.哈希的应用 5.海量数据处理面试题 unordered系列关联式容器 在c98中&#xff0c;STL提供了底层为红黑树结构的一系列关联式容器&#xff0c;在查询时效率可以达到logN&#xff0c;即最差的情况下需要比较红…

非常有趣的桌面萌宠互动软件

软件介绍 这里要介绍的软件是一款在主播直播领域十分实用的萌系插件&#xff0c;它能让主播的直播更具趣味性和吸引力。 软件开发者与特性 该软件由国外高中生kuroni开发&#xff0c;是一款开源软件。其最大的亮点在于&#xff0c;能让手鼓猫的手臂跟随鼠标和按键操作做出相…

InfluxQL 数据分析实战:聚合、过滤与关联查询全解析

InfluxQL 作为时序数据库的专用查询语言&#xff0c;在处理时间序列数据时展现出独特优势。本文深入探讨 聚合计算、数据过滤和跨测量关联 三大核心操作&#xff0c;通过真实代码示例展示如何从海量时序数据中提取关键洞察。文中涵盖从基础平均值计算到复杂多维度分析的完整流程…

记一次idea中lombok无法使用的解决方案

在注解处理器下&#xff0c;一般 Default 为“启用注解处理”和“从项目类路径获取处理器”&#xff0c;但是我的项目中的为选择“处理器路径”&#xff0c;导致了无法识别lombok&#xff0c;因此&#xff0c;需要改为使用“从项目类路径获取处理器”这个选项。如下图所示&…

【速通RAG实战:进阶】17、AI视频打点全攻略:从技术实现到媒体工作流提效的实战指南

一、AI视频打点的技术底层与数据处理流程 (一)视频内容结构化的核心技术栈 AI视频打点的本质是将非结构化视频数据转化为带时间戳的结构化信息,其技术流程涵盖音视频处理、语音识别、自然语言处理三大核心模块,形成“数据采集-内容解析-智能标记-协同应用”的完整闭环。 …

Java BigInteger类详解与应用

Java BigInteger类应用详解 BigInteger的构造方法&#xff1a; 对象一旦创建&#xff0c;内部的值不能发送改变 BigInteger常见的成员方法&#xff1a; 一、对象创建 BigInteger提供两种主要构造方式&#xff1a; // 通过字符串构造 BigInteger num1 new BigInteger("…

LLM优化技术——Paged Attention

在Transformer decoding的过程中&#xff0c;需要存储过去tokens的所有Keys和Values&#xff0c;以完成self attention的计算&#xff0c;称之为KV cache。 &#xff08;1&#xff09;KV cache的大小 可以计算存储KV cache所需的内存大小&#xff1a; batch * layers * kv-he…

Java并发编程实战 Day 1:Java并发编程基础与线程模型

【Java并发编程实战 Day 1】Java并发编程基础与线程模型 开篇&#xff1a;系列定位与学习目标 欢迎来到为期30天的《Java并发编程实战》系列教程。本系列将从Java并发编程的基础知识讲起&#xff0c;逐步深入到高级特性与实战应用&#xff0c;帮助开发者构建高性能、可扩展的…