【原】 POJ 2388 Who's in the Middle 中位数 解题报告
http://poj.org/problem?id=2388
方法:
找中位数
一般来讲当数不是很多时可使用patition的方法,复杂度n
这里的方法适用于大量数据的情况,此时内存无法放下所有数。通过扫描大概lgn次数据即可找到中位数,复杂度nlgn
利用了中位数的性质:其左右两边的数据量相同
Description
FJ is surveying his herd to find the most average cow. He wants to know how much milk this 'median' cow gives: half of the cows give as much or more than the median; half give as much or less.
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
* Line 1: A single integer N
* Lines 2..N+1: Each line contains a single integer that is the milk output of one cow.
Output
* Line 1: A single integer that is the median milk output.
Sample Input
5
2
4
1
3
5
Sample Output
3
Hint
INPUT DETAILS:
Five cows with milk outputs of 1..5
OUTPUT DETAILS:
1 and 2 are below 3; 4 and 5 are above 3.
1: #include "sort.h"
2:
3: using namespace std ;
4:
5: int MedianOfArray(int *a,int n)
6: {
7: int guess,maxlt,mingt ;
8: int less,equal,greater ;
9: int max=a[0],min=a[0] ;
10: int i;
11:
12: //the first pass find out the max and min
13: for( i=1 ; i<n ; ++i )
14: {
15: if( a[i] > max )
16: max = a[i] ;
17: else if( a[i] < min )
18: min = a[i] ;
19: }
20:
21: while(true)
22: {
23: guess = min+(max-min)/2 ;
24: maxlt = min ;
25: mingt = max ;
26:
27: less=equal=greater=0 ;
28:
29: //one pass througth the elements
30: //find out the numbers of elements less/equal/greater than the middle guess
31: //also find out the max elements less than guess , and the min elements greater than guess
32: for( i=0 ; i<n ; ++i )
33: {
34: if( a[i] < guess )
35: {
36: ++less ;
37: if( a[i] > maxlt )
38: maxlt = a[i] ;
39: }
40: else if( a[i] > guess )
41: {
42: ++greater ;
43: if( a[i] < mingt )
44: mingt = a[i] ;
45: }
46: else
47: ++equal ;
48: }
49:
50: if( less<=(n+1)/2 && greater<=(n+1)/2 ) //'less' and 'greater' are both less than half
51: break ;
52: else if( less > greater ) //less>=(n+1)/2 or greater>=(n+1)/2
53: max = maxlt ; //less>=(n+1)/2, so the median in the range [min,maxlt]
54: else if( greater > less ) //either 'less' or 'greater' greater or equal to (n+1)/2
55: min = mingt ; //greater>=(n+1)/2 , so the median in the range [mingt,max]
56: }
57:
58: //less<=(n+1)/2 && greater<=(n+1)/2
59: if( less == (n+1)/2 ) //左边够一半了(4/8 or 5/9),则取左边最大的元素即为中位数
60: return maxlt ;
61: else if( greater == (n+1)/2 ) //右边够一半了(4/8 or 5/9),则取右边最小的元素即为中位数
62: return mingt ;
63: else if( less+equal >= (n+1)/2 ) //左右都不够一半,则equal部分中的guess为中位数
64: return guess ;
65: }
66:
67: void run2388()
68: {
69: int n,val;
70: cin>>n;
71: int arr[10000];
72: int i=0 ;
73: for(i=0;i<n;++i)
74: cin>>arr[i];
75: cout<<MedianOfArray(arr,n)<<endl;
76: }
77:
78: //******************************************************
79:
80:
81: template<typename T>
82: void Qselect( T *a , size_t b , size_t e , int k )
83: {
84: if(b+10>=e)
85: InsertionSort(a+b,e-b+1) ;
86: else
87: {
88: int mid = Partition( a , b , e );
89: int midRank = mid+1 ;
90:
91: if( k == midRank )
92: return ;
93: else if( k < midRank )
94: Qselect( a , b , mid-1 , k );
95: else //k>midRank
96: Qselect( a , mid+1 , e , k );
97: }
98: }
99:
100: template<typename T>
101: T QuickSelect( T *a , size_t n , int k )
102: {
103: if(k>n)
104: {
105: cerr<<"k must be wrong"<<endl;
106: return -1;
107: }
108:
109: Qselect( a , 0 , n-1 , k );
110: return a[k-1] ;
111: }
112:
113: void run2388_Qselect()
114: {
115: int n,val;
116: cin>>n;
117: int arr[10000];
118: int i=0 ;
119: for(i=0;i<n;++i)
120: cin>>arr[i];
121: cout<<QuickSelect(arr,n,n/2)<<endl;
122: }