TOPK

堆排序
维护一个 n = k 的堆 PriorityQueue,for i < 数据量级来元素就加进去,如果超过了 k,就poll 堆顶元素

时间复杂度就是 数据量级 log K
空间复杂度,因为堆本质其实就是一数组,空间为 O k
类似快排法
使用hash
对于这种问题

字典树
混合查询

有一批文件,每个文件里面有很多单词,如何快速统计所有单词的出现次数?
数据重复、是否存在问题
位图
bitmap 其实就是对HashSet或者数组的一个压缩版
Java的BItSet
海量数据的极致优化还有 压缩位图
布隆过滤器
解决 return true 就表示 可能在 和 return false 就表示 一定不在的
解决的业务问题:

找出排名前500的数

| 方法 |
思路 |
时间复杂度 |
空间复杂度 |
优劣 |
| 方法1:逐个归并(维护 top500) |
先取第一个数组的后500个,然后与后续数组逐个合并,再保留最大500个 |
每次合并 500 + 500 → O(500),共 10000 次 → O(10000 × 500) = 5×10⁶ ≈ 5M |
O(500) |
简单稳定 |
| 方法2:多路堆(K 路最大堆) |
每个数组取最后一个元素(最大值)放入大顶堆,每次弹出一个并往回移动指针 |
每次堆操作 log10000,执行500次 → O(500 × log10000) ≈ 500 × 14 = 7000,外加初始化堆 10000 → 10000log10000≈ 140000 → 总约 15 万 |
O(10000 + 500) |
性能最优 |

堆本质上就是一颗完全二叉树
多路堆,最优解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| import java.util.*;
public class Top500FromSortedArrays {
static class Node { int value; int row; int index; Node(int value, int row, int index) { this.value = value; this.row = row; this.index = index; } }
public static List<Integer> top500(int[][] arrs) { int k = arrs.length; PriorityQueue<Node> maxHeap = new PriorityQueue<>( (a, b) -> b.value - a.value );
for (int i = 0; i < k; i++) { int lastIndex = arrs[i].length - 1; maxHeap.offer(new Node(arrs[i][lastIndex], i, lastIndex)); }
List<Integer> result = new ArrayList<>(); for (int count = 0; count < 500 && !maxHeap.isEmpty(); count++) { Node top = maxHeap.poll(); result.add(top.value);
if (top.index - 1 >= 0) { maxHeap.offer(new Node(arrs[top.row][top.index - 1], top.row, top.index - 1)); } } return result; }
public static void main(String[] args) { int[][] data = { {1, 3, 5, 7, 9}, {2, 4, 6, 8, 10}, {11, 12, 13, 14, 15} };
System.out.println(top500(data)); } }
|
两个大文件中找出共同URL

64 byte * 50 亿 ,一个文件 320g 全加载到内存 建立Hash表,那肯定是不现实的。
还是 分治
对A :hash(url) % 1000 -> 1000个小文件 命名为 a0,a1,a2….. a999
对B:同样,hash一定得相同
那么a99 和 b99里面可能存在相同的。但a99和a98里面的就不可能出现相同的
然后再把小文件加载到内存,建立hashmap