经典算法(一) top k
2018-01-19 18:08
169 查看
问题:1亿数据中,找出最大的k个数,要求使用内存不超过1m
(延伸问题:1亿数据中,找出重复出现次数最多的k个,要求使用内存不超过1m 等)
分析:
1亿数字(int)占内存:100000000 * 4byte / 1024 / 1024 =381m
其中 int=4byte,1m=1024kb,1kb=1024b
实现:
维护一个k大小的数组有序数组。每次加进来新的,都要判断是不是 换掉 该数组中最小的元素,如果需要,则删除最小元素,放入新元素,并重新排序。
基于小顶堆的实现:
创建一个k大小的堆。TOP K堆只用维护固定数量的元素,每次加进来新的,都要判断是否替换掉堆顶元素,如果需要,则删除堆顶元素,放入新元素,并重新构造堆
时间复杂度O(nlnK)
(延伸问题:1亿数据中,找出重复出现次数最多的k个,要求使用内存不超过1m 等)
分析:
1亿数字(int)占内存:100000000 * 4byte / 1024 / 1024 =381m
其中 int=4byte,1m=1024kb,1kb=1024b
实现:
维护一个k大小的数组有序数组。每次加进来新的,都要判断是不是 换掉 该数组中最小的元素,如果需要,则删除最小元素,放入新元素,并重新排序。
基于小顶堆的实现:
创建一个k大小的堆。TOP K堆只用维护固定数量的元素,每次加进来新的,都要判断是否替换掉堆顶元素,如果需要,则删除堆顶元素,放入新元素,并重新构造堆
时间复杂度O(nlnK)
public class TopK_ByHeapSort { //向小顶堆插入一个新的元素 public static void insertHeap(int[] heap, int value) { heap[0] = value; adjustHeap(heap, 0, heap.length);// 重新对堆进行调整 } //调整堆 public static void adjustHeap(int[] arr, int i, int length) { int temp = arr[i];// 先取出当前元素i for (int k = i * 2 + 1; k < length; k = k * 2 + 1) {// 从i结点的左子结点开始,也就是2i+1处开始 if (k + 1 < length && arr[k] > arr[k + 1]) {// 如果左子结点小于右子结点,k指向右子结点 k++; } if (arr[k] < temp) {// 如果子节点小于父节点,将子节点值赋给父节点(不用进行交换) arr[i] = arr[k]; i = k; } else { break; } } arr[i] = temp;// 将temp值放到最终的位置 } //构建小顶堆 public static void createMinHeap(int[] arr){ for (int i = arr.length / 2 - 1; i >= 0; i--) { adjustHeap(arr, i, arr.length); } } //交换元素 public static void swap(int[] arr, int a, int b) { int temp = arr[a]; arr[a] = arr[b]; arr[b] = temp; } //将小顶堆 转化为 有序数组 public static int[] minHeapToSortArr(int[] arr){ for (int j = arr.length - 1; j > 0; j--) { swap(arr, 0, j);// 将堆顶元素与末尾元素进行交换 adjustHeap(arr, 0, j);// 重新对堆进行调整 } return arr; } public static void print(int[] n) { for (int i = 0; i < n.length; i++) { System.out.print(" " + n[i]); } System.out.println(); } //使用堆排序实现topk public static int[] getTopKByHeap(int input[], int k) { //构建k大小数组 int[] result = new int[k]; for (int i = 0; i < k; i++) result[i] = input[i]; //构建小顶堆 createMinHeap(result); //将新元素插入小顶堆 for (int i = k; i < input.length; i++) { if (input[i] > result[0]) insertHeap(result, input[i]); // 复杂度最坏是O(nlgK),而且内存消耗就K,不然海量数据排序,内存放不下,得用归并排序,最好最坏平均都是 } //将小顶堆转化为有序数组 minHeapToSortArr(result); return result; } public static void main(String[] args) { int input[] = { 37, 3, 5, 29, 2, 9, 10, 40, 99 }; int k=6; print(getTopKByHeap(input, k)); } }
相关文章推荐
- Spark 编程实战之经典算法TOP K
- Top K 算法详解
- 【LeetCode-面试算法经典-Java实现】【225-Implement Stack using Queues(用队列实现栈操作)】
- 经典算法题每日演练——第八题 AC自动机
- java经典算法_037判断字符是否属于中文
- TOP K算法问题
- Java经典算法题(三)
- 算法系列15天速成 第五天 五大经典查找【中】
- 经典算法题--求对策字符串的最大长度
- 数据结构和算法经典100题-第7题
- 人脸识别经典算法二:LBP方法
- 数据结构经典算法学习之老鼠走迷宫02
- 经典的字符串模式匹配算法KMP算法
- 经典面试题(四)附答案 算法+数据结构+代码 微软Microsoft、谷歌Google、百度、腾讯
- 海量数据处理算法(top K问题)
- 【经典算法】——KMP,深入讲解next数组的求解
- 经典视觉跟踪算法TLD的剖析与展示
- 浅谈PHP第二弹---经典算法的运用(冒泡排序和快速排序)
- 数据挖掘十大经典算法(5) 最大期望(EM)算法
- [算法] 当今世界最为经典的十大算法--投票进行时