渣渣渣變渣渣系列(3)
阿新 • • 發佈:2019-02-07
一、題目描述:
二、演算法思想:
本演算法的巧妙之處在於充分利用主元素的定義,即在序列中個數超過半數的元素。那麼在動態統計的過程中,主元素出現的頻率要最大可能的大於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