這個題也是個比較有名的面試題.當然有很多變種.
題目意思基本是:從一個數據量很大的數組里找前N大的元素.不允許排序.
這個題有兩個比較好的思路:
思路一:用快速排序的思想,是思想,不是要排序;
思路二:用最大堆的思想.
我暫時只實現了思路一,思路二我之后實現了會補上.
思路一比較簡單了.我們先用快排的思想找出第n大的數,然后帶上后面n-1個就完事了.因為后面的都比支點數大.
怎么找第n大的數?我在之前的博客寫過,請移步到 找第n大的數
代碼:
#include<stdio.h> #include<stdlib.h> /*找出第n大的數的下標*/ int choose_nth(int a[], int startIndex, int endIndex, int n); /*找出前n大的數*/ void choose_max_n(int a[],int startIndex, int endIndex, int n); int main(int argc, char *argv) { int a[] = {1,4,111,32,45,1000,99,300,8,22,189}; int n,i; printf("數組是:\n"); int an = sizeof(a)/sizeof(int); for(i = 0; i < an; ++i) printf("%d ",a[i]); printf("\n"); printf("你想找最大的前面幾個數:"); scanf("%d",&n); choose_max_n(a, 0, an - 1, n); return 0; } void choose_max_n(int a[], int startIndex, int endIndex, int n) { int i = choose_nth(a, startIndex, endIndex, n); printf("最大的前N個數是:\n"); for(; i <= endIndex; ++i) printf("%d ",a[i]); printf("\n"); } int choose_nth(int a[], int startIndex, int endIndex, int n) { int midOne = a[startIndex]; int i = startIndex, j = endIndex; if(i == j) return i; if(i < j) { while(i < j) { for(; i < j; j--) if(a[j] < midOne) { a[i++] = a[j]; break; } for(; i < j; i++) if(a[i] > midOne) { a[j--] = a[i]; break; } } a[i] = midOne; int th = endIndex - i + 1; if(th == n) { return i; } else { if(th > n) { return choose_nth(a, i + 1, endIndex, n); } else { return choose_nth(a, startIndex, i - 1, n - th); } } } }
結果:
數組是: 1 4 111 32 45 1000 99 300 8 22 189 你想找最大的前面幾個數:5 最大的前N個數是: 99 111 300 1000 189
之后會補上用最大堆思想來做的代碼.