求一个给定数组的前k个数有多种方法一
方法一:排序取前k个数,时间复杂度nlogn
方法二:维护一个最大堆,时间复杂度nlogn
方法三:维护一个容量为k的最小堆,代码如下,时间复杂度O(nlogk)
#include
#include
#include
std::vector findKthLargest(std::vector& nums, int k)
{
// 维护一个k个元素的最小堆
// 先将前k个元素优先队列,遍历真个数组,如果数组比最小值大,弹出堆顶元素,入队列
// 时间复杂度 nlogk
std::vector res;
std::priority_queue, std::greater > pq(nums.begin(), nums.begin() + k);
for (int i = k; i < nums.size(); i++) {
if (nums[i] > pq.top()) {
pq.pop();
pq.push(nums[i]);
}
}
while (!pq.empty()) {
res.push_back(pq.top());
pq.pop();
}
return res;
}
int main()
{
std::vector arr;
std::vector res;
int n, k, temp;
std::cin >> n;
for (int i = 0; i < n; i++) {
std::cin >> temp;
arr.push_back(temp);
}
std::cin >> k;
res = findKthLargest(arr, k);
//std::cout << res.size();
for (int i = res.size() - 1; i >= 0; i--)
std::cout << res[i] << std::endl;
}
方法四:使用快排的操作加分治解决。
快排的第一步操作,使得存在一个标志位key,左边的数都小于这个数,右边的数都大于这个数,再次建立一个递归函数,使得右边的数字个数恰好是k即可
简单快排代码
void QuickSort(int arr[], int start, int end) {
if (start >= end)
return;
int k = arr[start];
int i = start, j = end;
while (i != j) {
while (j > i && arr[j] >= k)
j--;
std::swap(arr[i], arr[j]);
while (i < j&&arr[i] <= k)
i++;
std::swap(arr[i], arr[j]);
}
QuickSort(arr, start, i - 1);
QuickSort(arr, i + 1, end);
}
arrangeRight函数使得数组分成两半,标志位左边的数都小于它,标志位右边的数都大于它
如果右边的数的个数恰好等于k,那么直接返回
如果右边的数的个数小于k,这个数即为n,那么要往左边移动n-k个数过来
如果右边的数的个数大于k,递归到右边第i+1的位置。
void arrangeRight(int arr[], int m, int start, int end) {
int k = arr[start];
int i = start, j = end;
while (i != j) {
while (j > i && arr[j] >= k)
j--;
std::swap(arr[i], arr[j]);
while (i < j&&arr[i] <= k)
i++;
std::swap(arr[i], arr[j]);
}
if (end - i + 1 == m)
return;
else if (end - i + 1 > m)
arrangeRight(arr, m, i + 1, end);
else
arrangeRight(arr, m-end+i-1, start, i-1);
}
完整代码
#include
#include
#include
#define N 100000
void QuickSort(int arr[], int start, int end) {
if (start >= end)
return;
int k = arr[start];
int i = start, j = end;
while (i != j) {
while (j > i && arr[j] >= k)
j--;
std::swap(arr[i], arr[j]);
while (i < j&&arr[i] <= k)
i++;
std::swap(arr[i], arr[j]);
}
QuickSort(arr, start, i - 1);
QuickSort(arr, i + 1, end);
}
void arrangeRight(int arr[], int m, int start, int end) {
int k = arr[start];
int i = start, j = end;
while (i != j) {
while (j > i && arr[j] >= k)
j--;
std::swap(arr[i], arr[j]);
while (i < j&&arr[i] <= k)
i++;
std::swap(arr[i], arr[j]);
}
if (end - i + 1 == m)
return;
else if (end - i + 1 > m)
arrangeRight(arr, m, i + 1, end);
else
arrangeRight(arr, m-end+i-1, start, i-1);
}
int main()
{
int arr[N];
int n, k;
std::cin >> n;
for (int i = 0; i < n; i++)
std::cin >> arr[i];
std::cin >> k;
arrangeRight(arr, k, 0, n - 1);
QuickSort(arr, n - 1 - k - 1, n - 1);
for (int i = n - 1; i >= n - k; i--)
std::cout << arr[i] << std::endl;
}