使用分治和递归算法 - 求数组前k大的所有数(不事先排序)
#include <iostream>
using namespace std;
void PrintArray(int arr[], int s, int e)
{
for (int i = s; i < e; i++) {
cout << arr[i] << ' ';
}
cout << endl;
}
int ArrangeRight(int arr[], int start, int end, int numOfBigest)
{
int i = start;
int j = end - 1;
int key = arr[start];
int temp;
while (i != j) {
while (i < j && key <= arr[j])
j = j - 1;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
while (i < j && arr[i] <= key)
i = i + 1;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
if (end - i == numOfBigest) {
return i;
} else if (end - i > numOfBigest) {
return ArrangeRight(arr, i + 1, end, numOfBigest);
} else if (end - i < numOfBigest) {
return ArrangeRight(arr, start, i, numOfBigest - (end - i));
}
}
int main()
{
int vec[] = {3, 1, 2, 5, 10, 6, 30, 7};
cout << sizeof(vec)/sizeof(int) << endl;
int start = ArrangeRight(vec, 0, sizeof(vec)/sizeof(int), 4);
for (int i = 0; i < 4; i++) {
cout << vec[start+i] << ' ';
}
cout << endl << "Program End ... " << endl;
return 0;
}
- ArrangeRight函数首先利用类似快速排序把数组分为两部分(前部分比KEY值小,后部分比KEY值大)
- 如果是后部分的元素的数量和k相等,后部分正好是所有k大的数
- 如果是后部分的元素的数量大于k,说明k大的所有数还在后部分之中,继续递归求后部分的元素的k大的所有数(注意:起始位置应该是i+1,因为KEY值肯定是不在k大的所有元素中)
- 如果后部分的元素数量小于k,说明k大的所有数一定都在前部分之中,继续递归求前部分的元素的k大的所有数,去掉了后部分,求的问题就转化为是第(k-后部分元素数量)大的所有数了(注意:同上,因为KEY值肯定也不在k大的所有元素中)