尋找多數元素
一、問題描述:
令A[1.....n]是一個整數序列,A中的整數a如果在A中出現的次數多於[n/2]次,那麼a就稱爲多數元素。例如在序列1,3,2,3,3,4,3中,3是多數元素,應爲7個元素中它出現的次數是4。有幾種方法可以解決這個問題。
法【1】:蠻力算法
把每一個元素和其他元素比較,並且對每個元素計數,如果,
某個元素的計數大於[n/2],就可以斷言它是多數元素;否則,在序列中就沒有多數元素。但是,這樣的比較次數是n(n-1)/2=Θ(n²),這種方法的代價太昂貴。所以稱爲蠻力算法。
法【2】:排序算法
另外一種比較有效地算法是,對這些元素排序,並且計算每個
元素在序列中出現多少次。這在最壞的情況下的代價是Θ(n log n)。因爲在最壞情況下,排序這一步需要Ω(n log n)次比較。
法【3】:中間元素法
另外一種算法是尋找中間元素,就是第[n/2]元素。因爲多數
元素,在排序的序列中一定是中間元素,可以掃描這個序列來測試中間元素是否確實是多數元素。由於中間元素可以在Θ(n)時間內找到,這個方法要花費Θ(n)時間。
二、算法分析:
通過歸納法導出一個漂亮算法,可以很好的解決這個問題。
1、該算法基於以下結論:
在原序列中除去兩個不同的元素後,那麼在原序列中的多數元素在新序列中還是多數元素。
2、接下來是其算法過程:
將計數器置1,並令c=A[1],從A[2]開始,逐個地掃描元素,如果被掃描的元素和c相等,則計數器加1;如果元素不等於c,則計數器減1;如果所有的元素都已經掃描完畢並且計數器大於0,那麼返回c作爲多數元素的候選者。如果在c和A[j](1<j<n)比較時計數器爲0,那麼對於A[j+1,,,n]上的元素遞歸調用candidate過程。注意減少計數器就是以上的觀察結論中所訴去除兩個不同元素的思想的實現。
3、僞代碼形式如下:
算法:MAJORITY
輸入:n個元素的數組A[1....n]。
輸出:若存在多數元素,則輸出;否則輸出none。
1.c ←candidate(1)
2.count ←0
3.for j ←1 to n
4. if A[j]=c then count←count+1
5.end for
6.if count>[n/2] then return c
7.else return none
過程 candidate(m)
1.j←m; c←A[m];count←1
2.while j<n and count>0
3. j←j+1
4. if A[j]=c then count←count+1
5. else count←count-1
6.end while
7.if j=n then return c
8.else return candidate(j+1)
三、源代碼(c++):
#include<iostream>
using namespace std;
int candidate(int);
int *A;
int n;
int main()
{
cout<<"input n is:";
cin>>n;
A=new int[n+1];
cout<<"input n element!"<<endl;
for(int i=1;i<=n;i++)
{
cout<<"# "<<i<<" element is: ";
cin>>A[i];
}
int c,count=0;
c=candidate(1);
for(int j=1;j<=n;j++)
{
if(A[j]==c)
count++;
}
if(count>(n/2)) //check again,c is the majority element
cout<<"the majority element in array is: "<<c<<endl;
else
cout<<"none!";
delete[] A;
return 0;
}
int candidate(int m)
{
int j,c,count;
j=m;c=A[m];count=1;
while(j<n&&count>0)
{
j++;
if(A[j]==c)
count++;
else
count--;
}
if(j==n)
return c;
else
return candidate(j+1);
}
四、分析迭代過程:
輸入的序列爲0,5,1,0,0,0,5,0. n=8
Candidate(1)
j=1,c=0,count=1
j=2,A[2]=5(!=c),count=0
Candidate(3)
j=3,c=1,count=1
j=4,A[4]=0(!=c),count=0
Candidate(5)
j=5,c=0,count=1
j=6,A[6]=0(=c),count=2
j=7,A[7]=5(!=c),count=1
j=8,A[8]=0(=c),count=2
j=n return c (c=0)