Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 28486 | Accepted: 16504 |
Description
Given an odd number of cows N (1 <= N < 10,000) and their milk output (1..1,000,000), find the median amount of milk given such that at least half the cows give the same amount of milk or more and at least half give the same or less.
Input
* Lines 2..N+1: Each line contains a single integer that is the milk output of one cow.
Output
Sample Input
5 2 4 1 3 5
Sample Output
3
Hint
Five cows with milk outputs of 1..5
OUTPUT DETAILS:
1 and 2 are below 3; 4 and 5 are above 3.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <utility>
using namespace std;
int a[100000];
int median(int i, int j, int k)
{
if (a[i] > a[j])
if (a[j] > a[k])
return j;
else if (a[i] > a[k]) // a[j]<a[k]
return k;
else
return i;
else if (a[j] < a[k])
return j;
else if (a[i] < a[k])
return k;
else
return i;
}
int partion(int left, int right, int p)
{
swap(a[p], a[right]);
int pivot = a[right];
int i = 0;
int j = left;
for (i = left; i < right; i++) {
if (a[i] < pivot) {
swap(a[i], a[j]);
j++;
}
}
swap(a[j], a[right]);
return j;
}
#if 0
int partion(int left, int right, int pivot)
{
while (true) {
while(a[left] < pivot) left++;
while(a[right] > pivot) right--;
if (!(left < right)) return left;
swap(a[left], a[right]);
//left++;
}
}
#endif
int nth(int left, int right, int i)
{
if (left == right) return a[left];
int q = partion(left, right, median(left, right, (right-left)/2));
int k = q - left + 1;
if (i == k) return a[q];
else if (i < k)
return nth(left, q - 1, i);
else
return nth(q + 1, right, i - k);
}
int main()
{
int n = 0;
int i = 0;
scanf("%d", &n);
int j = n;
while(j--){
scanf("%d", &a[i++]);
}
int ret = nth(0, n-1, (n/2 + 1));
printf("%d\n", ret);
}
采用STL里面三数取中的方法取pivot,随机取pivot效果并不好
如果采用median_of_mdians算法,最坏复杂度是能到O(n),但是实际效果并不好。
如果要进一步优化,可以采用STL里面的方法,检测递归深度,如果过深就采用heap保障复杂度为O(nlogn)
STL里面目前gcc4.8.1并没有保障最坏复杂度为O(n)
以后可以持续关注