N個數裡面找出最大的k個數

2021-06-22 08:32:53 字數 2275 閱讀 9157

**出處

題目:給出n個無序的數,然後找出其中最大的k個數

解題思路:

首先測試資料有可能會有一億個數,資料量特別的大,資料庫不可能儲存這麼多的資料。如果直接sort排序,nlogn時間複雜度實在是太高,大於10^9。我們可以考慮對資料進行分塊讀取,每次讀取的資料塊大小應大於k。

不如先假設第一次讀取的資料塊前k個數最大,然後把k個數建成最小二叉堆。然後從第k+1個數開始,每個數都與堆頂的數值進行比較,如果數字i大於堆頂則把堆頂的元素的元素替換成i,再調整一次堆。最後讀取完資料之後,這個二叉堆裡面的元素就是從小到大排序好的最大k個數。

時間複雜度:

o(nlogk)

空間複雜度:

o(k)

證明過程:

為什麼求最大的k個用的不是最大堆,而是最小堆?最大堆堆頂的元素是最大的,往下的子樹越來越小,把n個數建成最大堆,那麼堆頂往下的k個數就是最大的k個數。但是時間複雜度o(nlogn)和空間複雜度o(n)太高!

排序時間複雜度很高,是因為進行了很多沒有用的判斷,我們只需要取最大的k個數,而排序則把n個數都從小到大排序好了。建立乙個k個數的最小堆,假設堆裡面的元素是最大的,當然只是假設。如果從m+1到n這些數只要有數大於最小堆堆頂的數,那麼假設就不成立,堆頂那個數就不符合,自然把它去掉,把新的數加進來,再重新調整堆,使得堆頂的元素最小。

為什麼要用最小堆呢?因為每次查詢這k個數裡面的最小的那個數就是堆頂,時間複雜度是o(1)。如果直接用陣列來儲存這k個數,雖然查詢的時間複雜度是logn,但是當把這個數插入陣列的時候,陣列比它小其他元素還需要往前平移,所以時間複雜度遠遠大於logn。由於每次調整堆的時間複雜度是logn。所以最小堆的做法的時間複雜度是

o(nlogk),而空間複雜度只有o(k)。

**1  c++的

stl庫優先佇列實現二叉堆:

[html]view plain

copy

#include 

<

stdio.h

>

#include <

stdlib.h

>

#include <

string.h

>

#include <

algorithm

>

#include <

queue

>

using namespace std;   

struct cmp   

};   

#define max 11000   

int a[max];   

using namespace std;   

priority_queue<

int,vector

<

int>

,cmp

>

q;   

int main()   

else   

}   

}   k=

0;   

while(!q.empty())  //這樣處理是為了最後乙個數列印時沒有空格   

for(i=0

;i<

k;i++)   

return 0;   

}  

**2 (陣列實現堆):

[html]view plain

copy

#include 

<

stdio.h

>

#define max 10001   

int a[max];   

void heapadjust(int r,int s,int t)  //篩選函式1   

r[i]=temp;   

}   

void heapsort(int r,int n)   //堆排   

for(i=n

;i>

1;i--)   

}   

void heapadjust2(int r,int s,int t)   //篩選函式2   

r[i]=temp;   

}   

int main()   

heapsort(a,m);   

for(i=m

+1;i

<

=n;i++)   

}   

heapsort(a,m);   

for(i=1

;i<

=m;i++)   

return 0;   

}  

N個數中找出最大的K個數

題目描述 有很多個 n個 無序的數,我們姑且假定它們各不相等,怎麼選出其中最大的若干個 k個 數呢?1.n 100,k 10的時候怎麼處理?2.n 1000,k 100呢?3.n 1億億個,k 100呢?如果這些數是整數的話,怎麼處理?如果是浮點數呢?如果這些數是整數,並且存在上界呢?如果將題目中的...

找出N個整數中最大的K個數

所謂 第 前 k大數問題 指的是在長度為n n k 的亂序陣列中s找出從大到小順序的第 前 k個數的問題。解法1 我們可以對這個亂序陣列按照從大到小先行排序,然後取出前k大,總的時間複雜度為o n logn k 解法2 利用選擇排序或互動排序,k次選擇後即可得到第k大的數。總的時間複雜度為o n k...

找出最大的前K個數

是程式設計之美裡的乙個問題,找出乙個列表中的最大的前k個數,最先想到,也是最簡單的思路是做乙個k長度的盒子,然後乙個乙個資料往裡放,有大的來了就把小的剔除掉。但是這樣的做法會導致盒子內部要是有序的。不然找不出誰是最小的,比較和剔除就不能做了 這個做法的複雜度是o n k 書裡面講了一種比較好的辦法,...