九度 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
此题的不同之处是最后的输出结果需要是排序过的,一般是不要求这个的。
最常见的解法就是使用快速排序和大顶堆。
方法一使用快速排序的思想,划分的操作不用改,对递归部分稍作修改
1 #include<stdio.h> 2 #include<algorithm> 3 using namespace std; 4 int partition(int arr[], int s, int e){//返回分裂位置 5 int x = arr[s];//中轴元素 6 int j = e+1; 7 int i = s; 8 while(i < j){ 9 while(i < e && arr[++i] <= x); 10 while(j > s && arr[--j] > x); 11 if(i >= j) break; 12 swap(arr[j], arr[i]); 13 } 14 arr[s] = arr[j]; 15 arr[j] = x; 16 return j; 17 } 18 int k; 19 void minK(int arr[],int start,int end){ 20 if(start >= end) return; 21 int index = partition(arr,start,end); 22 if(index == k) return; 23 //类似二分的思想,比快速排序要少一个递归 24 if(index > k) minK(arr,start,index-1); 25 else minK(arr,index+1,end); 26 } 27 const int M = 200001; 28 int n,arr[M]; 29 int main() 30 { 31 while(scanf("%d%d",&n, &k) != EOF){ 32 for(int i=0; i<n; i++){ 33 scanf("%d", &arr[i]); 34 } 35 --k; 36 minK(arr,0,n-1); 37 sort(arr,arr+k+1);//输出结果需要是排序的 38 for(int i=0; i<k; i++) 39 printf("%d ",arr[i]); 40 printf("%d\n",arr[k]); 41 } 42 return 0; 43 }
方法二使用 大顶堆。
1 #include <algorithm> 2 #include <cstdio> 3 using namespace std; 4 int n,k,a[200000]; 5 void adjustHeap(int idx){ 6 int l = idx*2 + 1; 7 int r = idx*2 + 2; 8 int largeIndex = idx; 9 //先检查边界。k即为要创建的堆的大小 10 while( l<k || r<k ){ 11 if(l<k && a[l] > a[largeIndex]) largeIndex = l; 12 if(r<k && a[r] > a[largeIndex]) largeIndex = r; 13 if(largeIndex != idx){ 14 //交换 root和子节点。 15 swap(a[idx], a[largeIndex]); 16 //交换之后继续调整子节点 17 idx = largeIndex; 18 l = idx*2 + 1; 19 r = idx*2 + 2; 20 }else{ 21 break; //无需调整 22 } 23 } 24 } 25 void buildHeap(){ 26 for(int i= (k-1)/2; i>=0; i--){ 27 adjustHeap(i); 28 } 29 } 30 int main(){ 31 while(scanf("%d%d", &n, &k) != EOF){ 32 for(int i = 0; i < k; i++) 33 scanf("%d", &a[i]); 34 buildHeap(); 35 for(int i = k; i < n; i++){ 36 scanf("%d", &a[i]); 37 if(a[0] > a[i]){ 38 swap(a[0],a[i]); 39 adjustHeap(0); 40 } 41 } 42 sort(a,a+k); 43 for(int i = 0; i<k-1; i++) 44 printf("%d ", a[i]); 45 printf("%d\n", a[k-1]); 46 } 47 }
效率差不多
越努力,越幸运