乱序数组中第k大的数(顺序统计量)
该问题是顺序统计量中十分经典的问题。
使用快排中的分区法,将第k大的数排序。若双向扫描分区加上三点中值法或绝对中值法,可以保证在 O(n) 时间里找出第k大的数。
补充:可以直接使用C++STL中的nth_element函数(一定注意使用形式!!!!)。
1 /* 2 * 第k大的数 3 */ 4 int part_(int arr[], int p, int r) 5 { 6 int b = p; 7 while (p <= r) { 8 while (p <= r && arr[p] <= arr[b]) p++; 9 while (p <= r && arr[r] > arr[b]) r--; 10 if (p < r) 11 swap(arr[r], arr[p]); 12 } 13 swap(arr[b], arr[r]); 14 return r; 15 } 16 int select(int arr[], int p, int r,int k) 17 { 18 int kp = 0; 19 while (1) { 20 kp = part_(arr, p, r); // 双向扫描分区 21 if (kp == k) return arr[kp]; 22 else if (kp > k) r = kp - 1; 23 else p = kp + 1; 24 } 25 } 26 int main() 27 { 28 int ar[10]; 29 srand((unsigned)time(nullptr)); 30 for (int i = 0; i <= 9; i++) 31 cout << (ar[i] = rand() % (15 - 1 + 1) + 1) << " "; 32 cout << endl; 33 // 打印第k大的数 34 int arr[10]; 35 for (int i = 0; i <= 9; i++) 36 arr[i] = ar[i]; 37 cout << select(ar, 0, 9, 9) << endl; 38 nth_element(arr, arr + 9, arr + 10); // 包头不包尾,要有尾后迭代器 39 cout << arr[9]<< endl; 40 return 0; 41 }