輸出最小的k個數
方案1:如果輸入的陣列可變,我們可以借助partion部分排序的思想,隨機選k值,經過排序後,k左邊的數都比k小,k右邊的數都比k大,這樣經過排序後,在k左邊的數字就是最小的k個數:
int partion(int*a, int n, int left, int right)
if(left >= right)
int key = a[right];
while (left < right)
a[right] = a[left];
if (left < right&&a[left] >= key)
a[right] = a[left];
}a[left] = key;
return left;
}void getlastnums(int*input, int n, int *out, int k)
int begin = 0;
int end = n - 1;
intindex = partion(input, n, begin, end);
while(index!=k-1)
else
for (int i = 0; i < k; i++)
out[i] = input[i];
}
但是方案一有明顯的限制:我們需要修改輸入的陣列,因為,partion會改變陣列的數字的順序,如果不修改陣列的順序該如何呢?
方案二:適合海量資料的處理
我們先建乙個大小為k個元素資料的容器用來儲存最小的k個數,接下來每次從輸出的n個資料的整數中讀取乙個數,如果容器裡面的元素的個數小於k,直接將輸出的元素插入到容器裡面,如果容器裡面的元素個數已經是k,表明容器已經滿了,此時比較下乙個插入的數字與容器的元素的最大值比較,小,用這個數字替換容器中的最大的元素,如果大,直接拋棄,直到輸入的元素全部插入容器
我們發現容器滿了會做三件事:一是在k個整數中找最大的數,二是有可能在這個容器中刪除最大的數,三:可能要插入乙個新的數字
這時我們很容易想到大堆,堆頂是最大元素,其他的元素都比堆頂要小,取堆頂的元素時間複雜度是o(1),堆的插入和刪除時間複雜度nlgn,如果用二叉樹來做總的效率就是nlgk
但是有個缺點就是插入和刪除都要重新調整堆
我們想到了紅黑樹,紅黑樹的插入,查詢,刪除的效率都是lgn
在stl中set和multiset都是基於紅黑樹實現
#include
#include
#include
#include
#include
using
namespace
std;
typedef
multiset
> inset;
typedef
multiset
> ::iterator setiter;
void _getleasenum(vector
&data, inset&leasenum, int k)
vector
::iterator it = data.begin();//迭代器遍歷輸入的陣列
for (; it < data.end(); it++)
else}}
}
查詢最大的K個數 查詢最小的K個數
使用乙個容器,大小為k 用這個容器來儲存這最大的或者最小的k個數。如果是找最大的k個數,那麼,每次和容器中的最小元素比較,如果最小的元素小於當前元素,那麼刪除這個最小的元素,同時將當前元素插入 如果是找最小的k個數,那麼就和容器中最大的元素比較。同理。容器用哪個呢?容器選擇用set,set本身就是排...
查詢最小的k個數
乙個整型陣列,有n個元素,可以含有重複元素。查詢該陣列中最小的k個數。1 對陣列快速排序,然後從前往後依次挑出最小的k個元素,時間複雜度 nlogn k nlogn 2 設定乙個容量是 k 的臨時陣列,掃瞄目的陣列,如果臨時陣列元素個數小於k,直接填入臨時陣列,如果臨時陣列元素個數大於k,找出臨時陣...
查詢陣列中最小k個數
思路 可採用大頂堆來實現 維護乙個規模為k的大頂堆。從前往後掃瞄陣列元素 若大頂堆的size小於k,則把當前元素插入大頂堆中 若小於k,若當前元素小於堆頂元素,則刪除堆頂元素,插入當前元素。考慮到從頭實現乙個大頂堆比較麻煩,這裡使用treeset容器,它提供有序的set。treeset底層實際使用的...