第一种方法是利用快速排序。
快速排序的基本步骤是:找到轴,然后分别对左边和右边的数进行快速排序。
轴的特性是:在轴左边的数都比轴小,在轴右边的数都比轴大。
如果轴的恰好在k位置,那么轴就是第k大的数。
// 输入数组a[l..r](含边界),返回第k大的数。
int QuickSort(int arr[], int l, int r, int k) {
if (l >= r) return arr[l];
int i = l;
int j = r;
int pivot = arr[i]; // 将最左边的数选为轴
while (i < j) {
// j指针不断左移,直到找到arr[j]<pivot, 即找到比轴小的数
while (i < j && arr[j] >= pivot) j--;
// 把比轴小的数挪到轴的左边
if (i < j) {
arr[i] = arr[j];
i++;
}
// i指针不断右移,直到找到arr[i]>=pivot,即大于等于轴的数
while (i < j && pivot > arr[i]) i++;
// 把大于等于轴的数挪到右边
if (i < j) {
arr[j] = arr[i];
j--;
}
}
// 把轴的数值放到i位置
arr[i] = pivot;
// 如果轴的位置恰好是i,则返回轴
if (k == i) return pivot;
// 如果要找的位置k在轴的左边
if (k < i)
return QuickSort(arr, start, i - 1);
// 如果要找的位置k在轴的右边
else
return QuickSort(arr, i + 1, last);
}
时间复杂度是O(n) [这边博客说的:https://blog.csdn.net/orangefly0214/article/details/86527462]
堆排序, 每次都能分一半. 堆排序是不用数据放进内存的算法。
堆排序算法的解释:https://www.cnblogs.com/ssyfj/p/9512451.html
二叉树的存储方式之一就是数组,所以数组也可以看成一棵完全二叉树。
找第k大的数,就维持一个容量为k的堆。遍历待查找数组,将每个数都放到堆里,比较小的、溢出来的就扔了。
放完一轮后,堆中最小的数就是第k大的数。
将元素插入堆的时间复杂度是O(log k),所以总时间复杂度是O(n log k)