您的位置:首页 > 其它

微软算法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

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;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: