微软算法100题05 查找最小的k 个元素
2015-10-21 18:45
423 查看
5.查找最小的k 个元素
题目:输入n 个整数,输出其中最小的k 个。
例如输入1,2,3,4,5,6,7 和8 这8 个数字,则最小的4 个数字为1,2,3 和4。
思路: 对于元素集合非常大的情况,比如上亿条数据,可以通过在内存中构造一个有限大小的大堆(heap)来处理
大堆的特性是根节点总是为堆内元素的最大元素
1.对前K个元素构造大堆,里面包含K+1个元素,下标为1的元素为head根节点,该根结点是堆中的最大元素
2.依次读取剩余元素 如果读到的元素比根节点大,则忽略,因为我们的目的是查找最小的K个元素,堆中的元素总是比根节点小,所以如果比根节点还大,那肯定比堆中其他元素还大
如果读到的元素小于根节点,则将根节点替换为该元素,为了保持堆的特性,需要依次将其与其左右节点比较,如果左或右节点大于改节点,则下移该元素与子元素交换(sink)
3. 在堆中,i元素的左节点坐标为2*i, 右节点为2*i+1
题目:输入n 个整数,输出其中最小的k 个。
例如输入1,2,3,4,5,6,7 和8 这8 个数字,则最小的4 个数字为1,2,3 和4。
思路: 对于元素集合非常大的情况,比如上亿条数据,可以通过在内存中构造一个有限大小的大堆(heap)来处理
大堆的特性是根节点总是为堆内元素的最大元素
1.对前K个元素构造大堆,里面包含K+1个元素,下标为1的元素为head根节点,该根结点是堆中的最大元素
2.依次读取剩余元素 如果读到的元素比根节点大,则忽略,因为我们的目的是查找最小的K个元素,堆中的元素总是比根节点小,所以如果比根节点还大,那肯定比堆中其他元素还大
如果读到的元素小于根节点,则将根节点替换为该元素,为了保持堆的特性,需要依次将其与其左右节点比较,如果左或右节点大于改节点,则下移该元素与子元素交换(sink)
3. 在堆中,i元素的左节点坐标为2*i, 右节点为2*i+1
package com.rui.microsoft; import java.util.Arrays; /** * 5.查找最小的k 个元素 题目:输入n 个整数,输出其中最小的k 个。 例如输入1,2,3,4,5,6,7 和8 这8 个数字,则最小的4 个数字为1,2,3 和4。 * */ public class Test05_FindKMinItems { public static void main(String[] args) { //int[] array = {1,2,3,5,5,6,7,8,4}; int[] array = {1,8,9,3,2,7,6,4,5}; int size = 4; int[] array01 = Arrays.copyOf(array, size); int[] array02 = Arrays.copyOfRange(array, array01.length, array.length); MaxHeap heap = new MaxHeap(size); for(int i = 0; i < array01.length; i++){ heap.insert(array01[i]); } for(int i = 0; i < array02.length; i++){ heap.updateHead(array02[i]); } for(int i = 0; i < heap.size+1; i++){ System.out.println(heap.get()[i]); } } static class MaxHeap{ private int[] array; private int size; //current position in array which is open for insertion private int pos = 1; //our MaxHeap has a fixed size public MaxHeap(int size){ this.size = size; array = new int[size+1]; } public void insert(int data){ //insert to the end of the array if(pos > size){ return; } int i = pos; this.array[pos++] = data; //start to swim up while(i>1){ if(array[i] < array[i/2])break; else{ swap(i, i/2); i /= 2; } } } //Update the head node (maximum node) of the heap with a different value public void updateHead(int data){ //head is always the first node in the array int head = array[1]; if(data >= head){ //the new data for head node is larger than the old one, just skip it //because it maintains the max heap definition: the root node is always the largest one //array[1] = data; return; }else{ array[1] = data; int i = 1; int j = i; while(i < (pos-1)/2 && i > 0){ //start to sink the head node j = i; if(array[i] > array[2*i] && array[i] > array[2*i + 1]) break; else{ i *= 2; if(array[i] < array[i+1])i++; swap(i,j); } } } } private void swap(int i, int j){ int tmp = array[i]; array[i] = array[j]; array[j] = tmp; } public int[] get(){ return this.array; } } }
相关文章推荐
- php面向对象编程_2
- Many2one类型的fields Compute得到的值 搜索
- Linux多线程基础学习(八)私有数据
- MySQL获取汉字的拼音首字母
- 项目3 -- 顺序串算法
- Google服务器架构图解简析
- 自定义控件时,初始化的注意事项
- xen虚拟化实战系列(十二)之xen虚拟机高可用之在线迁移
- Log4j源码阅读之四— 4000 doConfigure方法
- 用Redis存储Tomcat集群的Session
- Logcat过滤不需要的系统标签
- Android 内存管理 &Memory Leak & OOM 分析
- Linux Shell脚本逐行读取多个文件
- 大型网站服务器架构
- CodeForces 589G Hiring
- httpClient发送post请求
- 不足9位数 补0
- NavigationBar 添加、标题/左右按钮/颜色
- 什么是JavaScript?
- [Java] Java中的可变参数方法