利用分桶、堆与多路归并解决 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. 推荐4款基于.NET开源、功能强大的CMS建站系统

    前言 CMS系统作为一种强大的内容管理工具,在数字化时代发挥着越来越重要的作用.无论是个人博客还是大型企业官网,选择一个合适的CMS都能极大地提高效率和用户体验.今天大姚给大家推荐4款基于.NET开源 ...

  2. c# 无法捕获 System.NullReferenceException?

    ..在VS debug 模式下会"无法捕获" System.NullReferenceException......但是在release 或者外部运行是能捕获的. test cod ...

  3. spring-boot-@Valid和@Validated详解

    ---------------------------------------------------------------------------------------- 在实际的项目开发中,经 ...

  4. java线程池优化

    ThreadPoolExecutor机制 一.概述 1.ThreadPoolExecutor作为java.util.concurrent包对外提供基础实现,以内部线程池的形式对外提供管理任务执行,线程 ...

  5. 如何在 ASP.NET Core 中实现速率限制?

    在 ASP.NET Core 中实现速率限制(Rate Limiting)中间件可以帮助你控制客户端对 API 的请求频率,防止滥用和过载.速率限制通常用于保护服务器资源,确保服务的稳定性和可用性. ...

  6. 变量-python

    变量-python 1. 变量的定义 变量是存储数据的地方,在程序运行时,变量的值可以改变.变量的定义格式如下: 变量名 = 数据 例如: a = 10 b = "hello" c ...

  7. STM32IO口模拟IIC时序

    正点原子IIC讲解:https://www.bilibili.com/video/BV1o8411n7o9/?spm_id_from=333.337.search-card.all.click& ...

  8. Prometheus修改数据存储位置

    Prometheus修改数据存储位置 Prometheus的数据存储位置可以通过配置文件中的 --storage.tsdb.path 参数来指定.默认情况下,数据存储在Prometheus安装目录下的 ...

  9. [BZOJ3514] [Codechef MARCH14] GERALD07加强版 题解

    名字感觉挺奇怪的. 考虑离线算法.首先答案就是用 \(n\) 减去连完边后的生成树森林边数.生成树当然就可以用 \(lct\) 求解了.我是不会告诉你这个时候我已经开始想回滚莫队了的. 考虑当我们倒序 ...

  10. 基于stm32+esp8266通过阿里云物联网平台和MQTT实现智慧粮仓环境监测管理系统

    基于STM32+ESP8266通过阿里云物联网平台和MQTT实现智慧粮仓环境监测管理系统 技术要点:STM32f407.ESP8266.阿里云物联网平台IOT.MQTT.JSON数据解析. 1.功能与 ...