俊介三

一天更新一点,一天积累一点

导航

找最小K个数

Posted on 2013-04-08 13:33  俊介三在前进  阅读(202)  评论(0)    收藏  举报

题目描述:

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

采用堆排比较好,但最后一个数据超时了?

update(2013.4.16):

用我面B公司时被问到的一个方法就能过,晕~~
思路:类似快排的方法,每次递归地找k个数落入哪个部分。最后在sort一个这k个数就好,
代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
 
void partition(int*arr, int k, int start, int end){
    if(start>=end) return;
    int left = start;
    int right = end;
    int pivot = arr[left];
    while(left<right){
        while(left<right && arr[right]>pivot) right--;
        if(left<right) arr[left++] = arr[right];
        while(left<right && arr[left]<pivot) left++;
        if(left<right) arr[right--] = arr[left];
    }
    arr[left] = pivot;
 
    int left_size = left-start;
    int right_size = end - left;
    //printf("left_size=%d\nright_size=%d\n\n",left_size,right_size);
     
    //恰好k个最小的数
    if(left_size==k-1) return;
    else if(left_size<k-1){
        partition(arr, k-left_size-1, left+1, end);
    }else{
        partition(arr, k, start, left-1);
    }
}
 
//把最小的k个数放到数组前k个位置
void helper(int* arr, int n, int k){
    partition(arr, k, 0, n-1);
}
 
int arr[200005];
int main(){
    int n,k,i;
    while(scanf("%d %d", &n, &k)!=EOF){
        for(i=0;i<n;i++){
            scanf("%d", &arr[i]);
        }
 
        helper(arr,n,k);
 
        sort(arr, arr+k);
        for(i=0;i<k-1;i++)
            printf("%d ",arr[i]);
        printf("%d\n",arr[k-1]);
    }
    return 0;
}