尋找主元素演算法(時間複雜度O(N),C#)
主元素問題:大小為N的陣列A,其主要元素是一個出現次數超過N/2的元素。
最近在學習演算法,書上發現這樣一道題,並且提供了一種遞迴演算法的概要,但是感覺不是特別好(遞迴判斷(時間複雜度大於O(N)了),還要對N的奇偶做出判斷以及使用附加陣列B),網上看了一下有一個SEO排行最靠前的(不說名字了,感覺不好)說了O(N)的演算法但是說的又不清楚而且純看描述部分地方描述的也有問題,自己參考那個用C#重新實現了一下演算法並且進行了說明,時間複雜度一眼可見O(N)。
只貼出來演算法的方法程式碼,其他忽略,演算法的一些步驟原因寫了註釋:
private int FindMainElement(int[] A)
{
if (A.Length <= 0)
return -1;
else if (A.Length == 1)
return A[0];
#region 尋找候選元
int Count = 0;//計數器,當最後count>=0時說明Current是目前最多的元素,也就是候選元,再驗證是不是主元素
int Current = A[0];//當前元素,假設第一個是候選元
for (int i = 1; i < A.Length; i++)//只能確定找出來的是當前陣列最多的數——候選元
{
if (Current == A[i])//如果下一個數和當前的候選元相同則候選元權重+1
Count += 1;
else//有一個和候選元不同的就把權重-1,可以理解為抵消了
Count -= 1;
if (Count < 0)//小於0說明當前的候選元肯定不夠支付抵消的,當前所選不是主元素,即便是後面也肯定是還會變回來
{
if (i + 1 < A.Length)
{
Current = A[i + 1];
Count = 0;
}
else//迴圈裡肯定就是==了,也就是說當前是陣列最後一個了,到此可以肯定沒有主元素了
{
return -1;
}
}
}
#endregion
#region 驗證是不是主元素
Count = 0;//重置作用,下面驗證的時候用它來記錄候選元出現的次數
for (int i = 0; i < A.Length; i++)
{
if (A[i] == Current)
Count += 1;
}
if (Count > A.Length / 2)
return Current;
#endregion
return -1;
}