《程式設計之法》2 1尋找最小的k個數

2021-07-15 05:10:04 字數 2246 閱讀 2681

題目描述:陣列裡面有n個整數,請找出其中最小的k個數,要求時間複雜度盡可能低。

解法一:全部排序:

先對這個序列快速排序,再輸出前k個元素。時間複雜度為o(nlogn)+o(k);

#include #include using namespace std;

void sortfindk(int *nums, int k)

int main();

while(cin >> k)

sortfindk(nums, k);

return 0;

}

解法二:部分排序:

前k個數不做處理,從下標k開始遍歷陣列,利用選擇排序選擇出前k個數的最大值kmax,每遍歷乙個數x,將其與kmax作比較,若x=kmax,不更新陣列而繼續向前遍歷。時間複雜度為(n-k)o(k)=o(nk),需用到指標指向每次遍歷的最大值,則空間複雜度為o(1);

#include using namespace std;

int selectsort(int *nums, int k)

return max;

}void selectfindk(int *nums, int k)

} for(i = 0; i < k; ++i)

cout << nums[i] << " ";

cout << endl;

}int main();

while(cin >> k)

selectfindk(nums, k);

return 0;

}

解法三:用堆代替陣列:

用容量為k的最大堆儲存前k個數,建堆費時o(k),此時堆中元素時有序的,繼續遍歷剩餘n-k個數,每次遍歷到的新元素的值為x,將其與堆頂元素kmax作比較,若x

#include #include using namespace std;

//priority_queue, greater> heap; //從小往大排,為小頂堆

priority_queueheap; //預設從大往小排,為大頂堆

void heapfindk(int *nums, int k)

} for(i = 0; i < k; ++i)

cout << endl;

}int main();

while(cin >> k)

heapfindk(nums, k);

return 0;

}

我這裡是直接使用stl值的大頂堆,具體堆的構建與實現:見網頁:

構建堆的時間複雜度為o(n)的原因:堆是一棵完全二叉樹,故樹高為h = o(log2(n)),由於初始的結點有可能在第h層,故根結點最多需要h-1次父子結點顛倒到達第1層,第二層的結點最多需要h-2次父子結點顛倒到達第2層,第h-1層的結點最多需要1次父子結點顛倒到達第h-1層,建堆時間複雜度為:

s = 1*(h-1) + 2*(h-2) + 2^2*(h-3) + ... 2^(h-1)*1; 2s = 2*(h-1) + 2^2*(h-2) + 2^3*(h-3) + ... 2^h*1;

兩者錯位相減可得s = -(h-1) + 2 + 2^2 + 2^h,約等於2^(h+1),將h = log2(n)帶入,則時間複雜度為o(n);

至於每次更新堆,每次只需要對堆頂做處理,故時間複雜度為o(log2(n))。

解法四:線性選擇演算法

該演算法實際上是求乙個陣列中第k小的數,且時間複雜度為o(n),如果要輸出k個最小的數,找到陣列中第k小的數後,此時k的左半段的元素都比第k個數小,即已經找到了陣列中最小的k個元素,直接遍歷下標0~k-1的元素輸出即可,時間複雜度為o(n) + o(k) = o(n)。。

由於該演算法篇幅有點長,具體實現見我的另外一篇部落格:尋找陣列中第k大的數:平均情況下時間複雜度為o(n)的快速選擇演算法

舉一反三:

三元組的數量:給定乙個數列a1,a2,a3...an和m個三元組表示的查詢,對於每個查詢(i, j, k),輸出ai,ai+1,ai+2,...aj的公升序排列中的第k個數。

最好使用線性選擇演算法,可使時間複雜度變為o(i-j)。使用前三種解法都會使該演算法的複雜度超過o(i-j),具體思路可根據上述四個解法就行調整,就不細述了。

程式設計之美 尋找最大的K個數(最小堆實現)

尋找最大的k個數 堆 cpp 定義控制台應用程式的入口點。include stdafx.h include using namespace std static const int n 100 void minheapify int origin,int i,int heapsize void bu...

程式設計之美 尋找最大的K個數

有很多個無序數,我們姑且假定他們各不相等,怎麼挑選出其中最大的若干個數呢?如果這個資料量很大,比如1億個,如果所存資料是浮點型呢?我們該怎麼處理呢?分兩部分,第一部分是我個人的解答,第二部分是書上的解答 第一部分 1,如果這個問題裡的資料都是整數,這個問題利用hash對映應該很簡單,就是在開闢乙個陣...

程式設計之美 尋找最大的K個數

有很多個無序數,我們姑且假定他們各不相等,怎麼挑選出其中最大的若干個數呢?如果這個資料量很大,比如1億個,如果所存資料是浮點型呢?我們該怎麼處理呢?分兩部分,第一部分是我個人的解答,第二部分是書上的解答 第一部分 1,如果這個問題裡的資料都是整數,這個問題利用hash對映應該很簡單,就是在開闢乙個陣...