1. 程式人生 > >尋找主元素演算法(時間複雜度O(N),C#)

尋找主元素演算法(時間複雜度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;
        }