通过率 68% · 提交 400 · 通过 272
小慕正在处理一个项目,项目中有一个长度为 n 的无序数字数组,每个数字代表二叉树叶子节点的权值,且所有数字均大于等于 1。 小慕需要实现一个函数,根据输入的数字数组生成,并将该树按照输出。 为了确保输出的二叉树中序遍历结果统一,小慕增加了以下限制:二叉树节点中,左节点的权值小于等于右节点的权值,根节点的权值为左右节点权值之和。当左右节点权值相同时,左子树的高度小于等于右子树的高度。 注意:所有测试用例均有效,能够成功生成哈夫曼树。 提醒:哈夫曼树又称最优二叉树,是一种最短的二叉树。所谓树的带权路径长度,就是树中所有叶节点的权值乘上其到根节点的路径长度(若根节点为第 0 层,叶节点到根节点的路径长度为叶节点的层数)。
这类题属于华为 OD 机考真题方向中「100分 / 排序」方向的高频题型,通常考察对「100分 / 排序」的建模能力与边界条件处理。掌握本题的解题思路后,可举一反三应对同类真题方向,稳步提升机考通过率。
提示:带虚线的词点一下有通俗解释。
第一行输入为数组长度,记为N,1<=N<=1000
第二行输入无序数值数组,以空格分割,数值均大于等于1,小于100000
输出一个哈夫曼树的中序遍历的数组,数值间以空格分割
示例 1
输入示例
5 5 15 40 30 10
输出示例
40 100 30 60 15 30 5 15 10
时间限制 1000 ms · 内存限制 128 MB
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。
相关图解步骤
先看指定步骤补关键知识点,再回到本题完成标准输入输出。
普通的二叉树节点包括三个属性:值 val、左节点 left、右节点 right。 但本题构建哈夫曼树的过程还需要考虑到子树的高度,因此还需要储存一个 高度 属性 height。
本题的难点其实在于 如何构建哈夫曼树。
哈夫曼树的定义,用通俗易懂的话来理解就是:
满足上述定义的树就是哈夫曼树。 但为了保证构建出来的树是唯一的,以保证输出的二叉树中序遍历结果统一,题目还包含了如下描述: > 二叉树节点中,左节点权值小于等于右节点权值,根节点权值为左右节点权值之和。当左右节点权值相同时,左子树高度小于等于右子树。
这也要在后续的构建中考虑。
哈夫曼树通常用于各种数据压缩,譬如文件、图片、音频压缩,都会用到哈夫曼树。树上的节点值,在数据压缩中通常表示某些字符出现的次数。
我们先看一个具体的例子。对于例子,我们可以从叶节点开始进行哈夫曼树的构建,其过程如下:
从上述例子可以窥见我们构建哈夫曼树的逻辑: 总是在剩余节点中,挑选出值最小的两个节点进行组合,来作为一个新节点的左右子节点。其中:
最开始的时候,我们需要构建一个节点对象数组,其中包含了所有的叶节点。这些叶节点的左右节点均为 None,高度为 0。
这些叶节点会是构建哈夫曼树的基础。
我们需要在 node_lst 中挑选出两个值最小的节点,根据这两个节点来构建一个新节点 new_node。 由于需要挑选出值最小的两个节点,所以我们可以对 node_lst 进行排序。
新节点的值为这两个节点值的和,新节点的左节点为值较小的节点,新节点的右节点为值较大的节点。高度暂时先不考虑,设置为 0。
新节点需要重新加入 node_lst,在后续这个节点会继续作为树中的节点来构建树。
在只考虑节点值来构建树的过程中,我们默认了左节点的值是小于右节点的值的。 但题目中的描述存在这样一句话:当左右节点权值相同时,左子树高度小于等于右子树。 这意味着左节点的值可能等于右节点的值,且在相等的时候我们需要同时考虑两棵子树的高度。
所以我们在对 node_lst 进行排序的时候,要同时考虑每一个节点的高度。仍然优先按照节点值进行逆序排序,再按照高度进行逆序排序。修改代码:
而新节点的高度 height,等于弹出的两个左右节点的高度中的较大值再加 1,其中加 1 表示新节点带来的新增高度。
height 也要作为属性来构建 new_node。所以上述代码修改为:
上述的流程只是构建了一棵子树,我们需要重复上述过程,直到构建出一棵完整的哈夫曼树。 那么构建到什么程度说明哈夫曼树完全构建完毕了呢?答案是 当 `node_lst` 中只剩下一个节点的时候,那么这个剩下的唯一节点就是根节点。
因此整体的构建树的函数 build_tree() 如下:
构建完哈夫曼树之后,剩下的中序遍历就非常简单了。 在得到根节点 root = node_lst[0] 之后,直接套模板即可。
上述解法已经可以通过全部用例了,但如果想实现更优的时间复杂度,排序并取节点的这一步,可以用 堆排序即优先队列 来代替。 这样可以将构建树中 while 循环中的单步操作的时间复杂度从 O(NlogN) 降为 O(logN)。
登录后可查看你在本题的历史提交,以及每次的各用例通过情况。
© 2026 广州慕课网络科技有限公司 · 吴师兄学算法官网 版权所有