九度OJ 1371 最小的K个数 -- 堆排序

来源:互联网 发布:python ggplot facet 编辑:程序博客网 时间:2024/05/21 10:59

题目地址:http://ac.jobdu.com/problem.php?pid=1371

题目描述:

输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

输入:

每个测试案例包括2行:

第一行为2个整数n,k(1<=n,k<=200000),表示数组的长度。

第二行包含n个整数,表示这n个数,数组中的数的范围是[0,1000 000 000]。

输出:

对应每个测试案例,输出最小的k个数,并按从小到大顺序打印。

样例输入:
8 4
4 5 1 6 2 7 3 8
样例输出:
1 2 3 4

我们可以先创建一个大小为k的数据容器来存储最小的k个数字。接下来我们每次从输入的n个整数中读入一个数。如果容器中已有的数字少于k个,则直接把这次读入的整数放入容器之中;如果容器中已有k个数字了,也就是容器已满,此时我们不能再插入新的数字而只能替换已有的数字。我们找出这已有的k个数中最大值,然和拿这次待插入的整数和这个最大值进行比较。如果待插入的值比当前已有的最大值小,则用这个数替换替换当前已有的最大值;如果带插入的值比当前已有的最大值还要大,那么这个数不可能是最小的k个整数之一,因为我们容器内已经有k个数字比它小了,于是我们可以抛弃这个整数。

因此当容器满了之后,我们要做三件事情:一是在k个整数中找到最大数,二是有可能在这个容器中删除最大数,三是可能要插入一个新的数字,并保证k个整数依然是排序的。如果我们用一个二叉树来实现这个数据容器,那么我们能在O(logk)时间内实现这三步操作。因此对于n个输入数字而言,总的时间效率就是O(nlogk)

下面是用堆排序解决该问题的代码:

#include <stdio.h>  void HeapSort(int Array[], int len);void BuildMaxHeap(int Array[], int len);void ShiftDown(int Array[], int index, int len);void Swap(int *m, int *n);  int main(void){    int len;    int k;    int Array[200000];    int i;      while (scanf("%d %d", &len, &k) != EOF){                 //读入数据个数        for (i=1; i<=len; ++i)             //读入数据            scanf("%d", &Array[i]);        BuildMaxHeap(Array, k);        for (i=k + 1; i <= len; ++i){            if (Array[i] < Array[1]){                Array[1] = Array[i];                ShiftDown(Array, 1, k);            }        }        HeapSort(Array, k);        for (i=1; i<=k; ++i){            printf("%d", Array[i]);            if (i != k)                putchar (' ');        }        putchar ('\n');    }    return 0;}  void HeapSort(int Array[], int len){    int i;    int time = len;    for (i=0; i<len; ++i){        Swap(&Array[1], &Array[time]);        --time;        ShiftDown(Array, 1, time);    }}  void BuildMaxHeap(int Array[], int len){    int index = len/2;      for (; index>0; --index){        ShiftDown(Array, index, len);    }}void ShiftDown(int Array[], int index, int len){    while ((2*index) <= len || (2*index+1) <= len){        if (2*index+1 <= len){            if (Array[index] < Array[2*index] ||                Array[index] < Array[2*index+1]){                if (Array[2*index] > Array[2*index+1]){                    Swap(&Array[index], &Array[2*index]);                    index = 2*index;                }                else{                    Swap(&Array[index], &Array[2*index+1]);                    index = 2*index + 1;                }            }            else                break;        }        else{            if (Array[index] < Array[2*index]){                Swap(&Array[index], &Array[2*index]);                index = 2*index;            }            else                break;        }    }}  void Swap(int *m, int *n){             //交换数据    int tmp;    tmp = *m;    *m = *n;    *n = tmp;}

 

清橙OJ上相似的题目:http://blog.csdn.net/jdplus/article/details/19675351

九度OJ上相似的题目:http://blog.csdn.net/jdplus/article/details/19677345

参考资料:何海涛 -- 程序员面试题精选100题(05)-查找最小的k个元素[算法]

0 0
原创粉丝点击