topk問題:有 n (n>1000000)個數,求出其中的前k個最小的數。
力扣原題:最小的k個數
輸入整數陣列 arr ,找出其中最小的 k 個數。
方法一:大頂堆
思路:維護乙個大小為k的大頂堆,遍歷一次陣列,初始插入k個數,然後每遍歷乙個數,將其與堆頂比較,若比堆頂小,則堆頂彈出,該數入堆。
class
solution
}for
(int i =
0; i < k;
++i)
return vec;}}
;
時間複雜度:o(nlgk),維護堆花費o(lgk)時間,最壞情況插入n次,維護n次堆。
空間複雜度:o(k),堆大小k。
方法二:快速選擇(quickselect)
思路同快速選擇,快速選擇選出第k個數時,前k個數就是最小的k個數,正好完成題目的要求。
class
solution
}swap
(a[l]
,a[j]);
return j;
}
vector<
int>
getleastnumbers
(vector<
int>
& arr,
int k)
return;}
};//寫法二
class
solution
return j;
} vector<
int>
getleastnumbers
(vector<
int>
& arr,
int k)
else
}return vector<
int>
(arr.
begin()
, arr.
begin()
+ k);}
};
呼叫stl庫函式:
class
solution
};
時間複雜度:同quickselect,期望為o(n), 演算法導論9.2有證明。
最壞情況下的時間複雜度為 o(n^2)。情況最差時,每次的劃分點都是最大值或最小值,一共需要劃分 n−1次,而一次劃分需要線性的時間複雜度。
空間複雜度:最壞情況下的空間複雜度為 o(n)。最壞情況下需要劃分 n 次,即 select 函式遞迴呼叫最深 n−1 層,而每層由於需要 o(1) 的空間,所以一共需要 o(n)的空間複雜度。期望遞迴lgn次,空間複雜度為o(lgn),我也不知道為啥。
快速選擇問題(top k問題)
找到乙個陣列中第k大的資料 使用分治法,參考快速排序的思想,找原陣列中找到乙個樞紐元pivot,將陣列分為s1,pivot,s2 s1中的資料都是小於pivot,s2中的資料都是大於pivot 如果pivot 就是第k個陣列,直接返回 如果s1中資料多於k,第k個資料存在於s1,遞迴呼叫s1 如果k...
堆解決topK問題
小根堆取的話,複雜度過高o nlogn 資料量過大會超時 class solution 堆排序 小根堆 return ans void heap vector int arr start while start 1 else if arr 2 start 1 arr 2 start 2 else s...
Top k問題(線性時間選擇演算法)
問題描述 給定n個整數,求其中第k小的數。分析 顯然,對所有的資料進行排序,即很容易找到第k小的數。但是排序的時間複雜度較高,很難達到線性時間,雜湊排序可以實現,但是需要另外的輔助空間。演算法 linearselect s,k 輸入 陣列s 1 n 和正整數k,其中1 k n 輸出 s中第k小的元素...