1. 程式人生 > >渣渣渣變渣渣系列(3)

渣渣渣變渣渣系列(3)

一、題目描述:


二、演算法思想:

本演算法的巧妙之處在於充分利用主元素的定義,即在序列中個數超過半數的元素。那麼在動態統計的過程中,主元素出現的頻率要最大可能的大於1/2。由於是動態統計,所以可能在區域性範圍內可能出現誤判,當主元素在序列分佈不均時,可能一開始出現誤判,但最終是會被糾正的,這個是可以通過數學證明一下。由於是必要條件,所以在最後還要進行充分性驗證。

具體演算法可以分為以下兩步:

1)選取候選主元素:一次掃描所給陣列中的每個整數,將第一個遇到的整數Num儲存到c中,記錄Num的出現次數為1。若遇到的下一個整數仍為Num,則計數加1,否則計數減1。當計數減到0時,將遇到的下一個整數儲存到c中,計數重新記為1,開始新一輪的計數(此處是演算法的關鍵,通過這種方式模擬主元素出現的頻率應該大於1/2),即從當前位置開始重複上述過程,直到掃描完全部陣列元素。(必要性)

2)判斷c中元素是否是真正的主元素:再次掃描該陣列,統計c中元素出現的次數,若大於n/2,則為主元素,否則序列中不存在主元素。(充分性)

三、核心程式碼:

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


四、完整程式碼:

#include<stdio.h>
int Main_Search(int A[],int n);
void Print(int A[],int n);
int main()
{
    //int A[]={0,5,5,3,5,7,5,5};
    int A[]={1,2,3,0,1,1,0,0,1,1,1};
    int n=sizeof(A)/sizeof(int);
    Print(A,n);
    printf("%d\n",Main_Search(A,n));

    return 0;
}
int Main_Search(int A[],int n)
{
   int i;
   int c;//用c來儲存候選主元素
   c=A[0];//設定A[0]為候選主元素
   int counter=1;//,counter用來計數
   /*必要條件,動態統計,主元素出現的頻率應該大於1/2*/
   for(i=1;i<n;i++)
    {
        if(A[i]==c)
            counter++;//對A中候選主元素計數
        else
        {
            if(counter>0)//處理不是候選主元素的情況
                counter--;
            else
            {
                c=A[i];//更換候選主元素,重新計數
                counter=1;
            }
        }
    }
    /*充分性驗證,保證主元素出現的頻率大於1/2*/
    for(i=0;i<n;i++)
    {
        if(A[i]==c)
            counter++;//統計候選主元素的實際出現次數
    }
    if(counter>n/2)
        return c;//確認候選元素
    else
        return -1;//不存在主元素
}
void Print(int A[],int n)
{
    int i;
    for(i=0;i<n;i++)
        printf("%-3d",A[i]);
    printf("\n");
}


五、測試分析:

時間複雜度O(n),空間複雜度1