1. 问题
给你一个序列让你找出第k大
2. 解析
写出一个快排,选定key,当左区间比他小的数大于k则递归左区间,小于k,则当前k减去小于的值,递归右区间,等于k则这个数就是我们要找的数
3. 设计
int FindKthMax(int*list, int left, int right, int k) { int key = list[left]; int low = left, high = right; while (low < high) { while (list[high]>=key&&high > low) high--; list[low] = list[high]; while (list[low]<=key&&high>low) low++; list[high] = list[low]; } list[low] = key; /*实现一次快速排序*/ int l = right - low + 1; if (l == k) //若key处恰好为第k大数,直接返回 return key; else if (l < k) /*l<k说明第k大数在key左边序列中,此时为第k-l大的数*/ FindKthMax(list, left, low - 1, k - l); else /*l>k说明第k大的数在右边序列中,位置还是第k大的数*/ FindKthMax(list, low + 1, right, k); }
4. 分析
最坏复杂度O(nlogn)
5. 源码
https://github.com/Tinkerllt/algorithm-work.git
#include<iostream> using namespace std; int FindKthMax(int*list, int left, int right, int k); int main() { int i,n,k; while (cin >> n) { int *a = new int[n]; for (i = 0; i < n; i++) cin >> a[i]; cin >> k; cout << FindKthMax(a, 0, n - 1, k) << endl; } return 0; } int FindKthMax(int*list, int left, int right, int k) { int key = list[left]; int low = left, high = right; while (low < high) { while (list[high]>=key&&high > low) high--; list[low] = list[high]; while (list[low]<=key&&high>low) low++; list[high] = list[low]; } list[low] = key; /*实现一次快速排序*/ int l = right - low + 1; if (l == k) //若key处恰好为第k大数,直接返回 return key; else if (l < k) /*l<k说明第k大数在key左边序列中,此时为第k-l大的数*/ FindKthMax(list, left, low - 1, k - l); else /*l>k说明第k大的数在右边序列中,位置还是第k大的数*/ FindKthMax(list, low + 1, right, k); }