尋找一個序列中的主元素
阿新 • • 發佈:2019-02-12
何謂主元素?具體講,如果一個數組A[1..n]中超過半數的元素都相同時,該陣列被稱為含有一個主元素。 (a) 設計一個有效演算法,確定該陣列中是否含有一個主元素,如果有,找出這個元素。(b) 能否給出一個線性時間演算法?
注意,該陣列的元素之間可能不存在順序——即不能進行”A[i]<A[j]”的大小判斷,但是可以進行是否相等的判斷。普通的演算法即需要2個for迴圈,算出每個數字的個數,這比較簡單,這裡不再給出,時間複雜度為O(n^2)。
首先來看看如果可以比較大小:
時間複雜度為線性O(n),基於分治法的線性時間求主元素演算法。演算法思想中位數:數列排序後位於最中間的那個數。如果一個數列有主元素
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; }