利用分桶、堆与多路归并解决 TopK 问题:结果处理阶段解析

在处理大规模数据时,TopK 问题是一个常见且具有挑战性的任务,即从海量数据中找出最大(或最小)的 K 个元素。为了高效地解决这个问题,我们可以采用分桶、堆和多路归并相结合的方法。本文将详细剖析该方法中结果处理阶段的代码逻辑。

问题背景

TopK 问题在数据处理、搜索引擎、推荐系统等领域都有广泛的应用。为了高效解决该问题,我们采用了分桶、堆和多路归并的策略。具体步骤包括:首先将数据分桶,降低数据规模;然后在每个桶中使用最小堆找出局部的 TopK 元素;最后将每个桶的 TopK 元素合并到全局最小堆中

具体代码

`import java.util.*;

public class TopKSolution {

    public static List<Integer> topK(int[] nums, int k) {
// 步骤 1: 分桶
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for (int num : nums) {
min = Math.min(min, num);
max = Math.max(max, num);
}
// 桶的数量
int bucketSize = 10;
int bucketCount = (max - min) / bucketSize + 1;
List<List<Integer>> buckets = new ArrayList<>();
for (int i = 0; i < bucketCount; i++) {
buckets.add(new ArrayList<>());
}
// 将元素放入对应的桶中
for (int num : nums) {
int bucketIndex = (num - min) / bucketSize;
buckets.get(bucketIndex).add(num);
} // 步骤 2: 每个桶中使用最小堆找出 TopK
PriorityQueue<Integer> globalHeap = new PriorityQueue<>(k);
for (List<Integer> bucket : buckets) {
if (bucket.isEmpty()) continue;
// 为当前桶创建一个容量为 k 的最小堆,用于找出该桶内的 TopK 元素
PriorityQueue<Integer> localHeap = new PriorityQueue<>(k, Comparator.naturalOrder());
for (int num : bucket) {
if (localHeap.size() < k) {
localHeap.offer(num);
} else if (num > localHeap.peek()) {
localHeap.poll();
localHeap.offer(num);
}
}
// 将每个桶的 TopK 元素合并到全局堆中
for (int num : localHeap) {
if (globalHeap.size() < k) {
globalHeap.offer(num);
} else if (num > globalHeap.peek()) {
globalHeap.poll();
globalHeap.offer(num);
}
}
} // 步骤 3: 结果处理
List<Integer> result = new ArrayList<>(globalHeap);
result.sort(Collections.reverseOrder());
return result;
} public static void main(String[] args) {
int[] nums = {3, 2, 1, 5, 6, 4};
int k = 2;
List<Integer> topK = topK(nums, k);
System.out.println("Top " + k + " elements: " + topK);
}
} `

代码解释

分桶:

  1. 先找出数组里的最小值 min 和最大值 max。
  2. 确定桶的数量 bucketCount,这里每个桶的大小为 bucketSize。
  3. 把数组中的每个元素依据其值放入对应的桶中。

堆:

  1. 针对每个桶,使用最小堆 localHeap 找出该桶内的 TopK 元素。
  2. 要是堆的大小小于 K,就直接将元素加入堆;若堆的大小已达到 K 且当前元素比堆顶元素大,就移除堆顶元素并将当前元素加入堆。

多路归并:

  1. 把每个桶的 TopK 元素合并到全局最小堆 globalHeap 中。
  2. 最终从全局堆中获取最大的 K 个元素。

结果处理:

  1. 把全局堆中的元素存到列表里,然后按降序排序。

大量数据topk-分桶+堆+多路并归解决方案的更多相关文章

  1. 入门大数据---Hive分区表和分桶表

    一.分区表 1.1 概念 Hive 中的表对应为 HDFS 上的指定目录,在查询数据时候,默认会对全表进行扫描,这样时间和性能的消耗都非常大. 分区为 HDFS 上表目录的子目录,数据按照分区存储在子 ...

  2. 大数据学习----day27----hive02------1. 分桶表以及分桶抽样查询 2. 导出数据 3.Hive数据类型 4 逐行运算查询基本语法(group by用法,原理补充) 5.case when(练习题,多表关联)6 排序

    1. 分桶表以及分桶抽样查询 1.1 分桶表 对Hive(Inceptor)表分桶可以将表中记录按分桶键(某个字段对应的的值)的哈希值分散进多个文件中,这些小文件称为桶. 如要按照name属性分为3个 ...

  3. HIVE—索引、分区和分桶的区别

    一.索引 简介 Hive支持索引,但是Hive的索引与关系型数据库中的索引并不相同,比如,Hive不支持主键或者外键. Hive索引可以建立在表中的某些列上,以提升一些操作的效率,例如减少MapRed ...

  4. Hive 学习之路(五)—— Hive 分区表和分桶表

    一.分区表 1.1 概念 Hive中的表对应为HDFS上的指定目录,在查询数据时候,默认会对全表进行扫描,这样时间和性能的消耗都非常大. 分区为HDFS上表目录的子目录,数据按照分区存储在子目录中.如 ...

  5. Hive入门(三)分桶

    1 什么是分桶 上一篇说到了分区,分区中的数据可以被进一步拆分成桶,bucket.不同于分区对列直接进行拆分,桶往往使用列的哈希值进行数据采样.在分区数量过于庞大以至于可能导致文件系统崩溃时,建议使用 ...

  6. Hive 系列(五)—— Hive 分区表和分桶表

    一.分区表 1.1 概念 Hive 中的表对应为 HDFS 上的指定目录,在查询数据时候,默认会对全表进行扫描,这样时间和性能的消耗都非常大. 分区为 HDFS 上表目录的子目录,数据按照分区存储在子 ...

  7. Hive 教程(四)-分区表与分桶表

    在 hive 中分区表是很常用的,分桶表可能没那么常用,本文主讲分区表. 概念 分区表 在 hive 中,表是可以分区的,hive 表的每个区其实是对应 hdfs 上的一个文件夹: 可以通过多层文件夹 ...

  8. hive 分桶及抽样调查

    1.分桶的概述 分区提供了一个隔离数据和优化查询的遍历方式.不是所有的数据集都可形成合力的分区 对于一张表或者分区,hive可以进一步组织成桶,也就是更为细粒度的数据范围 分区针对的是数据的存储路径( ...

  9. Hive的分桶表

    [分桶概述] Hive表分区的实质是分目录(将超大表的数据按指定标准细分到指定目录),且分区的字段不属于Hive表中存在的字段:分桶的实质是分文件(将超大文件的数据按指定标准细分到分桶文件),且分桶的 ...

  10. Hive(六)【分区表、分桶表】

    目录 一.分区表 1.本质 2.创建分区表 3.加载数据到分区表 4.查看分区 5.增加分区 6.删除分区 7.二级分区 8.分区表和元数据对应得三种方式 9.动态分区 二.分桶表 1.创建分桶表 2 ...

随机推荐

  1. weixueyuan-Nginx负载均衡7

    https://www.weixueyuan.net/nginx/load_balanc/ Nginx负载均衡模块简述 Nginx 负载均衡是由代理模块和上游(upstream)模块共同实现的,Ngi ...

  2. Redis(3)---Redis事务|主从复制

    Redis事务 Redis 通过 MULTI .EXEC. DISCARD  和 WATCH 四个命令来实现事务功能. MULTI :标记一个事务块的开始. EXEC: 执行所有事务块内的命令. DI ...

  3. centos8网络配置问题

    由于RHEL8与centos8基本一样,所以以下方法同样适用于RHEL8 在centos8上进行网络配置时,出现以下问题: 意思是无法找到network.service 出现错误的原因是centos8 ...

  4. FTP、SFTP、TFTP,文件传输协议怎么选?

    转载:FTP.SFTP.TFTP,文件传输协议怎么选? FTP FTP(File Transfer Protocol,文件传输协议)是用于在计算机网络中传输文件的标准协议.FTP是一种客户端/服务器协 ...

  5. Ubuntu20.04配置CuckooSandbox环境

    Ubuntu20.04配置CuckooSandbox环境 因为最近要做恶意软件分析,阅读论文发现动态分析的效果普遍比静态分析的效果要好一些,所以需要搭建一个动态分析的环境,查阅资料发现Cuckoo S ...

  6. dart箭头函数和自执行函数的详解

    01==>箭头函数 // List list = ['苹果', '香蕉', '栗子']; // list.forEach((element) { // print(element); // }) ...

  7. Rocksdb原理简介

    本文分享自天翼云开发者社区<Rocksdb原理简介>,作者:l****n Rocksdb作为当下nosql中性能的代表被各个存储组件(mysql.tikv.pmdk.bluestore)作 ...

  8. Q:linux上某个磁盘挂载不上

    想把新创建的 /dev/datavg/data_lv 挂载到 /mysql 目录上 mkfs -t xfs -f /dev/datavg/data_lv mount /dev/datavg/data_ ...

  9. Maven配置多仓库

    一.配置说明 <?xml version="1.0" encoding="UTF-8"?> <settings xmlns="htt ...

  10. Hetao P3804 Cut 题解 [ 蓝 ] [ AC 自动机 ] [ 差分 ]

    Cut:AC 自动机简单题. 思路 看见多个模式串以及求前缀,很显然能想到构建一个 AC 自动机. 那么在用 \(T\) 查询时,当前指针的深度就是该位置的最长前缀匹配长度.这个在字典树 insert ...