題目描述:在未排序的數組中找到第 k 個最大的元素。請注意,你需要找的是數組排序後的第 k 個最大的元素,而不是第 k 個不同的元素。
這是一道排序問題?顯然當數組元素N很大時,採用一般O(N^2)的排序算法(如冒泡排序)一定會超時。
所以這裏可以使用快排和堆排。這裏快排和堆排的思想就不詳細介紹了,有興趣的可以去看我的其他文章或者直接baidu一下。
1.直接快速排序,對整個數組進行排序(156ms)
lass Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
quick_sort(nums, 0, nums.size() - 1);
return nums[nums.size() - k];
}
void quick_sort(vector<int>& nums, int l, int r){
if(l < r){
int pivot = partition(nums, l, r);
quick_sort(nums, l, pivot - 1);
quick_sort(nums, pivot + 1, r);
}
}
int partition(vector<int>& nums, int l, int r){
int p = nums[l];//i的位置已經記錄下來
int i = l, j = r;
while(i < j){
//先將大的往後移動
while(i < j && nums[j] >= p){
j --;
}
nums[i] = nums[j];//右邊第一個比p小的數
while(i < j && nums[i] <= p){
i ++;
}
nums[j] = nums[i];//左邊第一個比p大的數
}
nums[i] = p;
return i;
}
};
2.題目要求是找到第K個大的數即可,所以在quick_sort()函數中,每次partition返回的pivot的索引值和K進行比較,就可以每次減少一部分的排序:(52ms)
int quick_sort(vector<int>& nums, int l, int r, int k){
if(l == r) return nums[l];
int pivot = partition(nums, l, r);
if(pivot == nums.size() - k){
return nums[pivot];
}
else if(pivot > nums.size() - k){//比目標值大,在左邊
return quick_sort(nums, l, pivot - 1, k);
}
else{
return quick_sort(nums, pivot + 1, r, k);
}
}
3.在快排中,選擇pivot對於整體速度影響很大,所以這裏可以採用隨機選擇index的方法。在partition()中加入以下代碼:(16ms)
srand(time(NULL));//隨機種子
int r_pos = rand() % (r - l + 1) + l;
swap(nums[l], nums[r_pos]);
4.堆排序
建(大頂)堆-調整-堆排序(“取出前k個大的數即可”)
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
return buildHeap(nums, k);
}
int buildHeap(vector<int>& nums, int k){
//建成一個大頂堆
int n = nums.size();
for(int i = n / 2; i >= 0; -- i){
downAdjust(nums, i, n);
}
for(int j = 0; j < k; j ++){
swap(nums[0], nums[n - 1 - j]);
downAdjust(nums, 0, n - 1 - j);
//堆排序,將最大的,第二大的...,第k大的依次“取出”
}
return nums[n - k];
}
void downAdjust(vector<int>& nums, int i, int n){
//left & right child-node 2*i + 1 / 2*i + 2
int l = 2 * i + 1;
int r = 2 * i + 2;
int maxidx = i;
if(l < n && nums[l] > nums[maxidx]){
maxidx = l;
}
if(r < n && nums[r] > nums[maxidx]){
maxidx = r;
}
if(maxidx != i){
swap(nums[i], nums[maxidx]);//maxidx位置和原i位置交換
downAdjust(nums, maxidx, n);
}
}
};
以上就是這篇的主要內容,如有問題或疑惑,請您指出。謝謝!