大量数据topk-分桶+堆+多路并归解决方案

打印 上一主题 下一主题

主题 1716|帖子 1716|积分 5148

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
利用分桶、堆与多路归并解决 TopK 问题:效果处理阶段分析
在处理大规模数据时,TopK 问题是一个常见且具有挑战性的使命,即从海量数据中找出最大(或最小)的 K 个元素。为了高效地解决这个问题,我们可以采用分桶、堆和多路归并相结合的方法。本文将详细分析该方法中效果处理阶段的代码逻辑。
问题背景
TopK 问题在数据处理、搜索引擎、推荐系统等领域都有广泛的应用。为了高效解决该问题,我们采用了分桶、堆和多路归并的策略。具体步骤包括:首先将数据分桶,低落数据规模;然后在每个桶中利用最小堆找出局部的 TopK 元素;最后将每个桶的 TopK 元素合并到全局最小堆中
具体代码
  1. `import java.util.*;
  2. public class TopKSolution {
  3.     public static List<Integer> topK(int[] nums, int k) {
  4.         // 步骤 1: 分桶
  5.         int min = Integer.MAX_VALUE;
  6.         int max = Integer.MIN_VALUE;
  7.         for (int num : nums) {
  8.             min = Math.min(min, num);
  9.             max = Math.max(max, num);
  10.         }
  11.         // 桶的数量
  12.         int bucketSize = 10;
  13.         int bucketCount = (max - min) / bucketSize + 1;
  14.         List<List<Integer>> buckets = new ArrayList<>();
  15.         for (int i = 0; i < bucketCount; i++) {
  16.             buckets.add(new ArrayList<>());
  17.         }
  18.         // 将元素放入对应的桶中
  19.         for (int num : nums) {
  20.             int bucketIndex = (num - min) / bucketSize;
  21.             buckets.get(bucketIndex).add(num);
  22.         }
  23.         // 步骤 2: 每个桶中使用最小堆找出 TopK
  24.         PriorityQueue<Integer> globalHeap = new PriorityQueue<>(k);
  25.         for (List<Integer> bucket : buckets) {
  26.             if (bucket.isEmpty()) continue;
  27.             // 为当前桶创建一个容量为 k 的最小堆,用于找出该桶内的 TopK 元素
  28.             PriorityQueue<Integer> localHeap = new PriorityQueue<>(k, Comparator.naturalOrder());
  29.             for (int num : bucket) {
  30.                 if (localHeap.size() < k) {
  31.                     localHeap.offer(num);
  32.                 } else if (num > localHeap.peek()) {
  33.                     localHeap.poll();
  34.                     localHeap.offer(num);
  35.                 }
  36.             }
  37.             // 将每个桶的 TopK 元素合并到全局堆中
  38.             for (int num : localHeap) {
  39.                 if (globalHeap.size() < k) {
  40.                     globalHeap.offer(num);
  41.                 } else if (num > globalHeap.peek()) {
  42.                     globalHeap.poll();
  43.                     globalHeap.offer(num);
  44.                 }
  45.             }
  46.         }
  47.         // 步骤 3: 结果处理
  48.         List<Integer> result = new ArrayList<>(globalHeap);
  49.         result.sort(Collections.reverseOrder());
  50.         return result;
  51.     }
  52.     public static void main(String[] args) {
  53.         int[] nums = {3, 2, 1, 5, 6, 4};
  54.         int k = 2;
  55.         List<Integer> topK = topK(nums, k);
  56.         System.out.println("Top " + k + " elements: " + topK);
  57.     }
  58. }    `
复制代码
代码表明
分桶:

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

  • 针对每个桶,利用最小堆 localHeap 找出该桶内的 TopK 元素。
  • 要是堆的大小小于 K,就直接将元素参加堆;若堆的大小已到达 K 且当前元素比堆顶元素大,就移除堆顶元素并将当前元素参加堆。
多路归并:

  • 把每个桶的 TopK 元素合并到全局最小堆 globalHeap 中。
  • 最终从全局堆中获取最大的 K 个元素。
效果处理:

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

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

伤心客

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表