http://yilee.info/major-element-algorithm.html
http://www.cnblogs.com/ly772696417/archive/2012/03/22/2410921.html
何谓主元素?具体讲,如果一个数组A[1..n]中超过半数的元素都相同时,该数组被称为含有一个主元素。 (a) 设计一个有效算法,确定该数组中是否含有一个主元素,如果有,找出这个元素。(b) 能否给出一个线性时间算法?
注意,该数组的元素之间可能不存在顺序——即不能进行”A[i]<A[j]”的大小判断,但是可以进行是否相等的判断。普通的算法即需要2个for循环,算出每个数字的个数,这比较简单,这里不再给出,时间复杂度为O(n^2)。
首先来看看如果可以比较大小:
时间复杂度为线性O(n),基于分治法的线性时间求主元素算法。算法思想中位数:数列排序后位于最中间的那个数。如果一个数列有主元素,那么必然是其中位数。求一个数列有没有主元素,只要看中位数是不是主元素。找中位数的方法:选择一个元素作为划分起点,然后用快速排序的方法将小于它的移动到左边,大于它的移动到右边。这样就将元素划分为两个部分。此时,划分元素所在位置为k。如果k>n/2,那么继续用同样的方法在左边部分找;如果k<n/2就在右边部分找;k=n/2就找到了中位元素。根据快速排序的思想,可以在平均时间复杂度为O(n)的时间内找出一个数列的中位数。然后再用O(n)的时间检查它是否是主元素。。C语言源码如下:
int partition(int a[],int low,int high){
int pivotkey = a[low];
while(low<high)
{
if(low<high && a[high]>=pivotkey)
-–high;
if(low<high){
a[low]=a[high];
low++;
}
if(low<high && a[low]<=pivotkey)
++low;
if(low<high){
a[high]=a[low];
--high;
}
}
a[low]=pivotkey;
return low;}
//快排
void quick_sort(int a[],int low,int high){
if(low<high)
{
int position = partition(a,low,high);
if(position>n/2)
quick_sort(a,low,position-1);
else if(position<n/2)
quick_sort(a,position+1,high);
else
mid=a[position];//找到中位数
}
}
int main(){
int a[100];
printf("请输入个数n\n");
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
a[i]=0;//初始化
}
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
quick_sort(a,1,n);
int count=0;
for(int i=1;i<=n;i++)//中位数个数
{
if(a[i] == mid)
count++;
}
if(count > n / 2)
printf("有主元素为 %d 出现了 %d 次\n",mid,count);
else
printf("无主元素\n");
system("pause");
}
下面来开如果不可以比较大小只可以比较是否相等的情况:
下面来看看如果无序,不能比较大小的算法,具体思想就是“在一个集合中,删除两个不同的数,则集合的主元素保持不变。”根据这个原理,可以很快求出主元素。只有最后剩下的元素才可能是主元素。
#include <stdio.h>
int getMainElement(int a[],int len){
int i,mainElement,repeatTimes = 0;
//每次若不相同则减小这个计数,若相同则增加
for(i = 0;i<len;i++){
if(repeatTimes == 0){
mainElement = a[i];
repeatTimes = 1;
}
else{
if(mainElement == a[i])
repeatTimes++;
else
repeatTimes--;
}
}
return mainElement;
}
int main(){
while(1){
int len,i,mainElement,flagCount = 0;
scanf("%d",&len);
int *a = new int[len];
for(i = 0;i<len;i++){
scanf("%d",&a[i]);
}
mainElement = getMainElement(a,len);
for(i = 0;i<len;i++){
if(mainElement == a[i])
flagCount++;
}
if(flagCount>len/2)
printf("%d\n",mainElement);
else
printf("None\n");
}
return 0;
}