您的位置:首页 > 其它

众数问题-递归和分治

2015-04-07 14:10 204 查看
问题描述
       给定一个数组,找出其中出现次数最多的那个元素(即众数)。

例如:

1 2 2 2 3 5

众数是: 2

算法思路:先排序  后用分治法计算求解

分治法求解代码如下:

#include <iostream>
#include <stdlib.h>
#include <time.h>

using namespace std;

/*----------快速排序*/
int Partition(int *a , int l , int r)
{
int i = l , j = r+1;
int x = a[l];

while(true){
while(a[++i] < x && i < r);
while(a[--j] > x);
if(i >= j) break;
swap(a[i] , a[j]);
}
a[l] = a[j];
a[j] = x;

return j;
}

/*------------随机选择中位数排序*/
int RandomizedPartitiom(int *a , int l , int r)
{
srand(time(NULL));
int i = rand()%(r-l)+l;

swap(a[i] , a[l]);
return Partition(a , l , r);
}

/*----------------按中位数划分成两段*/
void split(int *a , int m , int l , int r , int *left , int *right)
{
int med = a[m];
*left = *right = m;
/*--------------------将 == 中位数的元素剔除:及 right-left+1 == 众数的个数*/
while(a[--(*left)] == med);
while(a[++(*right)] == med);
(*left)++;
(*right)--;
}

/*---------------分治法求解*/
void mode(int *a , int l , int r , int *largest , int *count)
{
int m = RandomizedPartitiom(a , l , r);//----查找中位数

int left , right;
split(a , m , l , r , &left , &right);//---按中位数分成2段

if(*largest < right-left+1){//-----保留众数个数最大值,及众数下标
*largest = right-left+1;
*count = m;
}
if(left-l > *largest) mode(a , l , left-1 , largest , count);//左边个数大于众数个数
if(r-right > *largest) mode(a , right+1 , r , largest , count);//右边个数大于众数个数
}

/*----------main()*/
int main()
{
int n;
cout<<"请输入集合S的元素个数n:"<<endl;
cin>>n;
int a
;
int largest = 0 , count = 0;
cout<<"请输入元素:"<<endl;
for(int i = 0 ; i < n ; i++)
cin>>a[i];
mode(&a[0] , 0 , n-1 , &largest , &count);
cout<<"众数是:"<<a[count]<<"\t重数是:"<<largest<<endl;
return 0;
}
/*
请输入集合S的元素个数n:
6
请输入元素:
1 2 2 2 3 5
众数是:2 重数是:3

Process returned 0 (0x0) execution time : 7.504 s
Press any key to continue.

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: