1. 程式人生 > >DS-008 順序表-尋找主元素

DS-008 順序表-尋找主元素

題目:已知一個整數序列A=(a0,a1,…,an-1),其中0≤ai<n(0≤i<n)。若存在ap1=ap2=…=apm=x且m>n/2(0≤pk<n,1≤k≤m),則稱x為A的主元素。例如A=(0,5,5,3,5,7,5,5),則5為主元素;又如A=(0,5,5,3,5,1,5,7),則A中沒有主元素。

假設A中的n個元素儲存在一個一維陣列中,請設計一個儘可能高效的演算法,找出A的主元素。若存在主元素,則輸出該元素;否則輸出-1。要求:

(1)給出演算法的基本設計思想。

(2)根據設計思想,採用C或C++或Java語言描述演算法,關鍵之處給出註釋。

(3)說明你所設計演算法的時間複雜度和空間複雜度。

分析:由題目中定義,主元素個數必須大於所有元素個數的一半,也可以說,主元素的個數比非元素個數之和還要多。

答:

(1)演算法思想:

選取備選主元素,用count記錄主元素個數和其他元素個數的差。初始時count為1,第一個元素為主元素,遇到主元素,count+1,遇到其他元素,count-1,count為0時,主元素定義在前半部分不滿足。如果存在主元素,必須在後半部分滿足定義,所以直接捨棄前半部分。將當前掃描的下一個元素暫定為主元素,count重新記為1,直到掃描完所有陣列。留下的那個元素有可能是主元素;統計上面得到的備選主元素的個數,驗證是否滿足主元素定義。

(2)演算法實現:

int Majority(int A[],int n){
    int i,c,count=1;            //c用來儲存候選主元素,count用來計數
    c = A[0];                   //設定A[0]位候選主元素
    for(i=1;i<n;i++)            //遍歷陣列,候選主元素是否滿足定義
        if(A[i]==c)
            count++;            //對A中的候選主元素計數
        else
            if(count>0)         //處理不是候選主元素的情況
                count--;
            else{               //count=0,更換候選主元素,重新計數
                c=A[i];
                count=1;
            }
    if(count>0)
        for(i=count=0;i<n;i++)  //統計候選主元素的實際出現次數
            if(A[i]==c)
                count++;
    if(count>n/2) return c;     //確認候選主元素
    else return -1;             //不存在主元素
}

(3)該演算法時間複雜度為O(n),空間複雜度為O(1)。

(如果上面的演算法太難想,不用糾結最優解,能解出來最重要)