九度OJ-题目1371:最小的K个数

来源:互联网 发布:c语言volatile的用法 编辑:程序博客网 时间:2024/05/18 00:34

题目链接地址:

九度OJ-题目1371:最小的K个数


题目描述:
输入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


解题思路:

输入n个整数,找出其中最小的K个数。这让我想到了选择排序,于是我便使用简单选择排序来挑选数组中最小的K个数,但是这种算法超时了。。。因此只能使用时间复杂度更低的堆排序来找出数组中最小的K个数了。

AC代码如下:

// 利用堆排序选择数组中最小的K个数#include<stdio.h>#define MAX 200001 int number[MAX]; /*** 输入n个整数,数组下标从1开始,若根结点为root,则其左孩子为2 * root,右孩子为2 * root + 1。* @param n  数组的元素个数* @return void*/void inputNNumber(int n){  int i;  for(i = 1;i <= n;i++)     scanf("%d",&number[i]);} /*** 打印最小的k个整数* @param n  表示数组的长度* @param k  表示需要输出最小元素的个数* @return void*/void printNMinNumber(int n,int k){  int i;  printf("%d",number[n]);  for(i = n - 1;i > n - k;i--)     printf(" %d",number[i]);  printf("\n");} /*** 交换两个数* @param a  整数a的地址* @param b  整数b的地址* @return void*/void swap(int * a,int * b){  int temp;  temp = *a;  *a = *b;  *b = temp;} /*** 调整生成小顶堆* @param root  待调整堆的根结点* @param n  待调整堆的元素个数* @return void*/void adjustMinHeap(int root,int n){   int min_index = root;   int leftChild;           // 小顶堆的左孩子结点   int rightChild;          // 小顶堆的右孩子结点   // 挑选出root结点,root结点的左孩子,root结点的右孩子这3个结点中的最小值做为小顶堆的根结点   // 调整后可能会破坏子小顶堆的结构,所以继续调整子堆的结构以使其满足小顶堆结构   while(min_index <= n)   {     min_index = root;     leftChild = 2 * root;     rightChild = 2 * root + 1;     if(leftChild <= n)  // 将根结点与左孩子进行比较,必须满足leftChild <= n这个条件,否则访问number[leftChild]会发生runtime error错误     {        if(number[leftChild] < number[min_index])           min_index = leftChild;     }     if(rightChild <= n) // 将根结点与右孩子进行比较,必须满足rightChild <= n这个条件,否则访问number[rightChild]会发生runtime error错误     {        if(number[rightChild] < number[min_index])           min_index = rightChild;     }     if(min_index != root)     {       swap(&number[root],&number[min_index]);       root = min_index;                       // 继续调整以min_index为根结点的子堆     }     else                                      // 表明小顶堆已经调整好了     {         break;     }   } //while} /*** 通过堆排序找出最小的k个元素* @param n  堆中元素的个数* @param k  找出堆中最小元素的个数* @return void*/void heapSort(int n,int k){  int i;  // 从最后一个非叶子结点开始自下而上构建初始的小顶堆  for(i = n / 2;i >= 1;i--)       // n / 2为最后一个非叶子结点  {    adjustMinHeap(i,n);  }  // 依次挑选出最小的k个元素  for(i = n;i > n - k;i--)  {    swap(&number[1],&number[i]);    // 将堆的最后一个元素与第一个元素进行交换    // 因为number[i]已经在排好序的序列中,所以将其剔除出堆    // 再从剩余堆number[1,i-1]的堆顶元素开始自上而下重新调整小顶堆的堆结构    adjustMinHeap(1,i - 1);  }  printNMinNumber(n,k);} int main(){  int n,k;  while(EOF != scanf("%d%d",&n,&k))  {     inputNNumber(n);     heapSort(n,k);  }  return 0;} /**************************************************************    Problem: 1371    User: blueshell    Language: C++    Result: Accepted    Time:840 ms    Memory:1800 kb****************************************************************/

0 0
原创粉丝点击