输出前 m 大的数
假设数组长度为 n,要输出前m大的数,m < = n,想法有两种:
- 先排序后输出,算法复杂度为 O(n log n)
- 先在 O(n)时间内将前m大的数放到数组的右边,然后对其进行快排O(mlogm),时间复杂度为 O(n+mlogm)。
在m较小,n较大的情况下,第二种做法显然比较可取。
那么如何在 O(n)的时间内将前m大的数放在数组的右边呢。
我们引入 arrangeRight(k):即把前K大的数放在数组的最右边。
同快排一样,我们选取一个位置 a = key[0],我们为 a 选择一个合适的位置,保证左边的数小于等于 a,右边的数大于等于a。然后判断 a右边的数组的数目和左边的数目
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| void swap(int & a, int & b){ int tmp = a; a = b; b = a; }
void qsort(int a[], int s, int e){ if(s >= e){ return; } int k = a[s]; int i = s; int j = e; while(i != j){ while(j > i && a[j] >= k) j--; swap(a[i], a[j]); while(i < j && a[i] <= k ) i++; swap(a[i], a[j]); } qsort(a, s, i - 1); qsort(a, i + 1, e); }
void arrangeRight(int a[], int k, int s, int e){ int key = a[s]; int i = s; int j = e; while(i != j){ while(i < j && a[j] >= key) j--; swap(a[i], a[j]); while(i < j && key >= a[i]) i++; swap(a[i], a[j]); } if(i == e - k + 1 ) return; else if(i + k > e + 1) arrangeRight(a, k, i, e); else if(i + k < e - 1) arrangeRight(a, k-a, s, i - 1); }
int a[6] = {1,3,4,56,7,1}; int k = 2; arrangeRight(a, 2, 0, 5); qsort(a, e - k + 1, e); print...
|
Last updated:
Thanks for your reading :) | URL
https://joshuaqyh.github.io/2019/04/02/分治-输出前K大的数/