难度:medium
类别:divide and conquer
1.题目描述
Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.
For example,
Given [3,2,1,5,6,4] and k = 2, return 5.
Note:
You may assume k is always valid, 1 ≤ k ≤ array’s length.
2.算法分析
直接按照前面的思路来,用归并排序进行排序,然后直接得到第k大的数,时间复杂度同样是O(nlogn)
3.代码实现
// created by YunaLin
// 2017-09-16
// kth largest number in the unsorted array
#include <iostream>
#include <vector>
using namespace std;
// merge sort the array
void mergeSort(vector<int>& arr, int min, int max);
void combineSub(vector<int>& arr, int min, int mid, int max);
int findKthLargest(vector<int>& nums, int k);
int main() {
int n, value;
vector<int> nums;
int k;
cin >> n;
for (int i = 0; i < n; ++i) {
cin >> value;
nums.push_back(value);
}
cin >> k;
cout << "the kth largest: " << findKthLargest(nums, k) << endl;
}
int findKthLargest(vector<int>& nums, int k) {
int n = nums.size();
if (n == 0 || (k > n) || (k <= 0 )) return -1;
mergeSort(nums, 0, n - 1);
return nums[n - k];
}
void mergeSort(vector<int>& arr, int min, int max) {
// 注意结束条件的判断
if (min >= max) return;
int mid = (min + max)/2;
// 递归,时间复杂度为O(nlogn)
mergeSort(arr, min, mid);
mergeSort(arr, mid + 1, max);
combineSub(arr, min, mid, max);
}
void combineSub(vector<int>& arr, int min, int mid, int max) {
// 因为两个子数组已经是排序了的,所以只需要不断地比较第一个数,
// 然后往后移动直到将所有的数字放到一个总的数组里面即可
int i = min, j = mid + 1;
vector<int> temp;
while (i <= mid && j <= max) {
if (arr[i] < arr[j]) {
temp.push_back(arr[i++]);
} else if (arr[i] > arr[j]) {
temp.push_back(arr[j++]);
} else {
temp.push_back(arr[i++]);
temp.push_back(arr[j++]);
}
}
while (i <= mid) {
temp.push_back(arr[i++]);
}
while (j <= max) {
temp.push_back(arr[j++]);
}
for (int i = min; i <= max; ++i) {
arr[i] = temp[i - min];
}
}
4.小结
在课本中有一种算法是随机选择一个数字,然后将数组分为比该数小、与该数相等、比该数大三个小组,判断第k大的数字是在哪个小组,然后不断分治下去得到最终的结果。在这种情况下,可以得到O(n)的时间复杂度,但是直接使用归并排序实现起来比较简单容易,所以就直接选用归并排序进行实现。