1. 程式人生 > >尋找一個序列中的主元素

尋找一個序列中的主元素

何謂主元素?具體講,如果一個數組A[1..n]中超過半數的元素都相同時,該陣列被稱為含有一個主元素 (a) 設計一個有效演算法,確定該陣列中是否含有一個主元素,如果有,找出這個元素。(b) 能否給出一個線性時間演算法?

注意,該陣列的元素之間可能不存在順序——即不能進行”A[i]<A[j]”的大小判斷,但是可以進行是否相等的判斷。普通的演算法即需要2for迴圈,算出每個數字的個數,這比較簡單,這裡不再給出,時間複雜度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;
}