• 【原】 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: }
  • 相关阅读:
    写代码随想
    学生管理系统
    自定义栈
    位运算符加密
    自定义Vector
    二叉树排序
    双向循环链表
    双向链表
    加载properties文件
    通讯录
  • 原文地址:https://www.cnblogs.com/allensun/p/1870218.html
Copyright © 2020-2023  润新知