算法每一题,成长每一天~
C0E45 生成哈夫曼树
真题链接:【持续更新】2024华为 OD 机试E卷 机考真题库清单(全真题库)
思路
Java
package com.ccr.paper_f;
import java.util.*;
public class C0E45 {
static List<Node> nodes = new ArrayList<>();
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
Integer[] arr = new Integer[n];
for (int i = 0; i < n; i++) {
arr[i] = in.nextInt();
}
Arrays.sort(arr, Comparator.reverseOrder()); // 降序排序
int sum = Arrays.stream(arr).mapToInt(Integer::intValue).sum();
Node root = new Node(sum);
Node node = root; // 根节点
for (int i = 0; i < arr.length - 2; i++) {
node = node.addChild(arr[i], false);
}
node.addChild(arr[arr.length - 2], true); // 最后两片叶子
int result = nodes.stream()
.filter(x -> x.isLeaf)
.mapToInt(x -> x.height * x.value)
.sum();
System.out.println("带权路径长度:" + result);
// 中序遍历
midOrder(root);
}
// 中序遍历
static void midOrder(Node node) {
if (node == null) {
return;
}
midOrder(node.left);
System.out.print(node.value + " "); // 中序:根节点在中间处理
midOrder(node.right);
}
static class Node {
int value;
int height; // 高度
boolean isLeaf; // 是否为叶子节点
Node left;
Node right;
public Node(int value) {
this.value = value;
this.height = 0;
}
public Node addChild(int v, boolean end) {
// 叶子
Node node = new Node(v);
node.height = this.height + 1;
node.isLeaf = true;
// 同层的非叶子
Node part = new Node(this.value - v);
part.height = this.height + 1;
part.isLeaf = end; // 最后两个都是叶子
if (v <= this.value / 2) {
this.left = node;
this.right = part;
} else {
this.right = node;
this.left = part;
}
nodes.add(node);
nodes.add(part);
return part; // 返回同级的非叶子节点
}
}
}
总结
1、创建 Node 对象,简化创建节点的逻辑。
2、记住 前序
、中序
、后序
遍历的区别:
方式 | 规则 |
---|---|
前序 | 根节点 > 左节点 > 右节点 |
中序 | 左节点 > 根节点 > 右节点 |
后序 | 左节点 > 右节点 > 根节点 |
算法要多练多练多练!!