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;
}