using namespace std;
int arrange(int* array, int begin, int end) {
if (begin == end) {
return begin+1;
}
int selected = array[begin];
int left = begin+1;
int right = end;
while (1) {
if (left > right) {
break;
}
for (;right >= begin + 1; right--) {
if (array[right] <= selected) {
break;
}
}
if (left > right) {
break;
}
for (;left <= end; left++) {
if (array[left] > selected) {
break;
}
}
if (left > right) {
break;
} else if (left < right) {
int tmp = array[left];
array[left] = array[right];
array[right] = tmp;
left++;
right--;
}
}
int tmp = array[right];
array[right] = array[begin];
array[begin] = tmp;
return right + 1;
}
void findKthNum(int * array, int k, int begin, int end) {
int kth = arrange(array, begin, end);
// cout<<begin<<" "<<end<<" "<<kth<<" "<<k<<endl;
if (kth == k) {
cout<<array[k-1]<<endl;
} else if (kth > k) {
findKthNum(array, k, begin, kth - 2);
} else if (kth < k) {
findKthNum(array, k, kth, end);
}
}
int main() {
while(1) {
int a[10000];
int cowNum;
cin>>cowNum;
if (cin.eof()) {
return 0;
}
for (int i = 0; i < cowNum; i++) {
cin>>a[i];
}
// int k;
// cin>>k;
findKthNum(a, cowNum/2 + 1, 0, cowNum-1);
cout<<endl;
}
}
C++ 94ms
这道题其实就是求中位数, 题目还很贴心的说明了数组的长度一定是奇数,来方便求。
这道题其实解法很多, 直接排序都行, 正好现在在看 算法导论 求第k个数那一章, 自己以前没有亲自动手搞过, 于是就用了求第k个数这种办法,
即求第N/2+1(中间)的数。
这种题可以说是我最怕的, 因为有多个循环,以及复杂的边界条件(其实大多数算法题都这样), 事实证明, 在这道题AC以后,仍是不敢肯定,
循环不变式让我清晰和肯定了一些, 但是感觉还是差了点。
每次先用辗转交换法把数组变成一某个数为边界左边全部<=, 右边全部>的数组,这样就可以得到该数在数组中是第几个(因为直接用的都是在整个数组的序号进行
运算, 所以不用考虑局部名次和全局名次的关系)。 如果返回的次序k正好是N/2+1,皆大欢喜,
否则, 如果k<N/2+1,那么中位数一定在该数右边的部分,如果k>N/2+1, 那么中位数一定在该数的左边的部分,递归求解即可.
因为用了全部名次, 所以递归不需要传递局部名次的起点,方便了点.
计数排序应该是解该题的最简单办法。
缺点: 占用数据多, 如果数据范围太大就悲剧.
C++ 79ms
#include <iostream>
#include <cstring>
using namespace std;
const int MILKMAX = 1000000;
int cowInfo[MILKMAX+1];
void findMiddle(int * cowInfo, int cowNum) {
int curNum = 0;
int max = cowNum/2 + 1;
for (int i = 1; i <= MILKMAX; i++) {
curNum += cowInfo[i];
if (curNum >= max) {
cout<<i<<endl;
break;
}
}
}
int main() {
while(1) {
int a[10000];
memset(cowInfo, 0, sizeof(cowInfo));
int cowNum;
cin>>cowNum;
if (cin.eof()) {
return 0;
}
for (int i = 0; i < cowNum; i++) {
cin>>a[i];
cowInfo[a[i]]++;
}
findMiddle(cowInfo, cowNum);
cout<<endl;
}
}