經典演算法:超大陣列,取出最大N數
阿新 • • 發佈:2019-02-05
轉載於:http://blog.csdn.net/yanzi1225627/article/details/8109035
這裡先講一種類似於快速排序的方法。注意題目要求,不要求完全排序,只要求最快解決問題!這個題是我面試NI公司時,對方問我的。原話是從1億個資料裡,找出前一百個最大的。
首先看原始碼吧:
void findMaxN(int a[], int start, int end, int N)//從陣列a裡,找出前N個最大的。如果是a[100],則start = 0, end = 99.注意這個索 引問題 { int mid = (start + end)/2; int i = start, j = end; while(i<j) { while(i<j && a[i]<=a[mid]) i++; while(i<j && a[j]>=a[mid]) j--; swap(a[i], a[j]); } /*注意這個while出來之後,i一定是等於j的,且從i 到 end是較大的那一端*/ if(end-i+1 == N) return; if(end - i+1 > N) findMaxN(a, i, end, N); else findMaxN(a, start, i, N - (end -i +1)); }
再來詳細說說思路,如果您看懂了快速排序對此一定不會陌生。首先拿a[mid] 做基準值,然後讓i, j從兩端開始遍歷,如果索引小的那一端資料小於基準值a[mid], 就往前遍歷,如果 左邊的大於了a[mid], while迴圈會跳出,記住這時的a[i] 是大於a[mid],
然後類似的思路,從j那一端遍歷,當右邊的資料a[j ] 小於基準值a[mid],則小while迴圈會跳出。然後會執行swap()這個函式,將兩個值進行交換 。 這樣最外面的while迴圈出來之後,i一定是等於j的,注意這裡i 和j不一定等於當前域中的mid。而且從i到end都是較大的,然後看看較大的那一端的資料有多少個,然後進行遍歷。
如果已經等於要找的N個,則跳出函式。如果大於N,則要從i到end為區間內接著找;如果小於N,比如說要找前50個最大的,結果end-i+1才等於20,也就是從i到end有20個較大的數,這就需要從 start(第一次時,可以認為是0)到i 區間內再找50-20 = 30個最大的。
至於swap的函式,利用引用實現如下:
void swap(int &a, int &b)
{
int temp = a;
a = b;
b= temp;
}
最後說說,如果這個函式執行完畢了,我怎麼訪問找到的最大的N個數呢? 很簡單,假設陣列長度為n, 從a[n-1], a[n-2]。。。順序取N個數,就是找到的最大的前N個數據了!這個演算法的最大情況時間複雜度是o(n的平方),最好情況是o(n), 平坦下來也是o(n).
等我空我介紹第二種思路,上面程式碼是即興寫的,原始碼我一會上傳。