劍指 Offer 40 最小的k個數

2022-06-11 18:12:08 字數 2284 閱讀 9250

對原陣列從小到大排序後取出前 k 個數即可。

時間複雜度:o(nlogn),其中 n 是陣列 arr 的長度。演算法的時間複雜度即排序的時間複雜度。

我們用乙個大根堆實時維護陣列的前 kk 小值。首先將前 kk 個數插入大根堆中,隨後從第 k+1k+1 個數開始遍歷,如果當前遍歷到的數比大根堆的堆頂的數要小,就把堆頂的數彈出,再插入當前遍歷到的數。最後將大根堆裡的數存入陣列返回即可。

時間複雜度:o(nlogk),其中 n 是陣列 arr 的長度。由於大根堆實時維護前 k 小值,所以插入刪除都是 o(logk) 的時間複雜度,最壞情況下陣列裡 n 個數都會插入,所以一共需要o(nlogk) 的時間複雜度。

空間複雜度:o(k),因為大根堆裡最多 k 個數。

1

class

solution 19}

2021

while(!q.empty())

2526

return

res;27}

28 };

這裡可以參考:《演算法導論(第3版)》的9.2和9.3節。

我們可以借鑑快速排序的思想。我們知道快排的劃分函式每次執行完後都能將陣列分成兩個部分,小於等於分界值 pivot 的元素的都會被放到陣列的左邊,大於pivot的都會被放到陣列的右邊。

與快速排序不同的是,快速排序會根據分界值的下標遞迴處理劃分的兩側,而這裡我們只處理劃分的一邊,並返回分界值pivot的下標i。但是劃分**和快速排序中的**是一模一樣的。

所以演算法步驟如下:

(1)編寫partition()函式,與快速排序的元素劃分**一模一樣,選擇區間最左側的元素為pivot,將乙個區間內所有小於pivot的數放在左邊,大於pivot的數放在右邊,然後返回pivot的下標i。

(2)對每次劃分之後pivot的下標和k進行判斷:

如果劃分之後的下標pivotindex剛好等於要找的第k個數的下標(下標從零開始,所以此處為k-1), 說明arr[pivotindex]就是要找的第k個數,又由於pivotindex左邊的數都小於arr[pivotindex],

所以左邊的數就是最小的k個數,則將這k個數裝入答案陣列;

如果劃分之後的下標pivotindex大於要找的第k個數的下標,則遞迴處理左半區間[left, pivotindex-1] ;

如果劃分之後的下標pivotindex小於要找的第k個數的下標,則遞迴處理右半區間[pivotindex+1, right] 。

對於最好的情況:每次所選的pivot劃分之後正好在陣列的正中間,那麼遞迴方程為t(n) = t(n/2) + n,解得t(n) = o(n),所以此時此演算法是o(n)線性複雜度的。

對於最壞的情況:每次的劃分點都是最大值或最小值,即每次所選的pivot劃分之後都好在陣列最邊上,一共需要劃分 n - 1次,而每次劃分需要o(n)的時間複雜度,所以此時此演算法時間複雜度為o(n2)。

可以改進:改進選取主元的方法,使每次選出的主元在劃分之後都能接近陣列的中間位置,這樣每次劃分都能減少當前區間一半元素的工作量,可以使最壞情況下的時間複雜度降為o(n)。關於這種改進後的主元選取方法,見《演算法導論(第3版)》的9.3節和這篇bfprt演算法的文章。

空間複雜度:期望為 o(logn),遞迴呼叫的期望深度為 o(logn),每層需要的空間為 o(1),只有常數個變數。最壞情況下的空間複雜度為 o(n)。最壞情況下需要劃分 n次,而每層由於需要 o(1)的空間,所以一共需要 o(n) 的空間複雜度。

1

class

solution 78

/*和快速排序的劃分**一模一樣

*/9 vector partition(vector& arr, int k, int left, int

right)

1920

swap(arr[left], arr[i]);

2122

//先判斷,有選擇的對左半邊或者右半邊進行遞迴

劍指offer40 最小的k個數

輸入n個整數,找出其中最小的k個數。注意 資料保證k一定小於等於輸入陣列的長度 輸出陣列內元素請按從小到大順序排序 樣例 輸入 1,2,3,4,5,6,7,8 k 4 輸出 1,2,3,4 思路1 用大頂堆儲存k個數,然後不斷的遍歷陣列,若是陣列中的數小於堆頂元素,則替換。實踐複雜度為o nlogk...

劍指offer40 最小的 K 個數

題目描述 輸入n個整數,找出其中最小的k個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4,思路 方法一 維護乙個大小為k的大頂堆,複雜度 o nlogk o k 特別適合處理海量資料 public class solution priorityqueuemax...

劍指offer40 最小的k個數

問題描述 輸入n個整數,找出其中最小的k個數。例如輸入4,5,1,6,2,7,3,8這8個數字,則最小的4個數字是1,2,3,4,方法1 o nlogn def getleastnumbers input,k input.sort return input 4 a sorted input inpu...