最接近中位数的k个数

问题描述:

         给定由n个互补相同的数组成的集合S以及正整数k<=n,试设计一个O(n)时间算法找出S中最接近S的中位数的k个数。

算法分析:

         首先,通过select算法得到这个数组的中位数,然后最这个集合中的每一个数都减去这个中位数然后取abs();最后在第二步得到的集合中,取第k小的数,再取小于第k小的数的k-1个数,他们原来的数,就是要求的k个数。PS:此算法有缺陷,要求保证绝对值数组中无重复,否则无法线性。


转自:http://hi.baidu.com/cosersoft/item/d6fba1cc9d40493298b4989c


算法实现:

#include <iostream>
using namespace std;
const int ArraySize=7;
const int Array[ArraySize]={2,63,11,23,434,333,1};//原始数组
int a[ArraySize];//查找数组
int b[ArraySize];
int Select(int temp[],int p , int r , int k);//选择在数组temp中,第k大的数字
int partition(int p ,int r);
void absArray(int midNum);
int main()
{
         for (int j=0;j<ArraySize;j++)
         {
                   a[j]=Array[j];//从原始数组copy数据
         }
         int k;
         cout<<"Default Array is : {2,63,11,23,434,333,1}."<<endl;
         cout<<"Please input the number k :"<<endl;
         cin>>k;
         int mid=(ArraySize+1)/2;
         int numMid=Select(a,0,ArraySize-1,mid);//得到中位数
         cout<<"中位数是 :"<<numMid<<endl;
         absArray(numMid);//生成绝对值数组
         int kNum=Select(b,0,ArraySize-1,k);
         cout<<"最接近的 "<<k<<" 个数为:";
         for (int i=0;i<ArraySize;i++)
         {
                   if(b[i]<=kNum) cout<<Array[i]<<" ";
         }
         cout<<endl;
         return 0;
}
int partition(int temp[],int p ,int r)
{
         int i=p-1;
         int j=r+1;
         int x=temp[p];
         while(true)
         {
                   while (temp[++i]<x && i<r);
                   while(temp[--j]>x);
                   if (i>=j) break;                                                                                                   
                   int tempNum=temp[i];
                   temp[i]=temp[j];
                   temp[j]=tempNum;
         }
         temp[p]=temp[j];
         temp[j]=x;
         return j;
}
int Select(int temp[],int p , int r , int k)
{
         if(p==r) return temp[p];
         int i=partition(temp,p,r);
         int j=i-p+1;
         if (k<=j)
         {
                   return Select(temp,p,i,k);
         }
         else return Select(temp,i+1,r,k-j);
}
void absArray(int midNum)
{
         for(int i=0;i<ArraySize;i++)
         {
                   b[i]=abs(Array[i]-midNum);
         }
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值