zoukankan      html  css  js  c++  java
  • 九度OJ 1371 最小的K个数 -- 堆排序

    题目地址: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 ('
    ');
        }
        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个元素[算法]

  • 相关阅读:
    好好活,做有意义的事
    linux运维、架构之路-linux基础知识
    linux运维、架构之路-linux目录结构
    linux运维、架构之路-linux基础优化
    linux运维、架构之路-SSH远程管理服务
    linux运维、架构之路-实时同步方案
    linux运维、架构之路-nfs网络文件系统
    linux运维、架构之路-全网备份项目方案
    linux运维、架构之路-rsync
    编程题
  • 原文地址:https://www.cnblogs.com/liushaobo/p/4373820.html
Copyright © 2011-2022 走看看