眾數(Mode)算法


  1.求眾數有很多種解法,直覺上第一種就是用哈希表統計,這種方法需要O(n)的時間和空間。另一種叫摩爾投票法,需要O(n)的時間和O(1)的空間,比哈希表要好,這種投票法先將第一個數字假設為眾數,然后把計數器設為1,比較下一個數和此數是否相等,若相等則計數器加1,否則計數器減1.然后看此時計數器的值,若為0,則將下一個值設為候選眾數。以此類推直到遍歷完整個數組,當前候選眾數即為該數組的眾數。精妙!通俗的講,他是把原數組精簡化,相互抵消。首先是有個強大的前提存在,就是眾數一定存在。如果計數器減到0了,說明目前不是候選者的數字的個數已經跟候選者出現的個數相同了,那么這個候選者已經很weak,不一定能出現超過半數,我們選擇更換當前的候選者。那么可能你會有疑問,那萬一后面又大量出現了之前的候選者怎么辦,不需要擔心,如果之前的候選者在后面大量出現的話,其又會重新變為候選者,直到最終驗證成為正確的眾數。

using System;
using System.Windows.Forms;

namespace repo.素材
{
    public partial class ModeSolve : Form
    {
        public ModeSolve()
        {
            InitializeComponent();
        }
        /// <summary>
        /// 求眾數
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            // 
            int[] numer = new int[] { 3, 3, 0, 1, 3, 2, 4 };
            int mresult = majorityElement(numer); //majorityElementIO(numer);

            // 
            System.Diagnostics.Debug.WriteLine(mresult);
        }
        /// 哈希表統計,需要O(n)的時間和空間。
        /// 摩爾投票法,需要O(n)的時間和O(1)的空間。
        /// 位操作方法  需要O(n)的時間和>O(n)的空間。

        // 摩爾投票法-目前只能適用於眾數個數>數組個數一般的情況
        public int majorityElement(int[] nums)
        {
            int cnt = 1;
            int res = nums[0];
            for (int i = 1; i < nums.Length; i++)
            {
                //也可直接遍歷數組for(int num:nums)
                if (cnt == 0)
                {
                    res = nums[i];
                }
                if (res == nums[i]) ++cnt;
                else --cnt;
            }
            // 不能得出眾數驗證
            int resNumber = 0;
            for (int i = 0; i < nums.Length; i++)
            {
                if (res == nums[i])
                {
                    resNumber++;
                }
            }
            if (resNumber >= nums.Length/2)
            {
                return res;
            }
            else
            {
                return 2147483647;
            }
        }
        // 位操作法-未調試
        public int majorityElementIO(int[] nums)
        {
            int res = 0, n = nums.Length;
            for (int i = 0; i < 32; ++i)
            {
                int ones = 0, zeros = 0;
                for (int num=0; num< n;num++)
                {
                    if (ones > n / 2 || zeros > n / 2) break;
                    if ((num & (1 << i)) != 0) ++ones;
                    else ++zeros;
                }
                if (ones > zeros) res |= (1 << i);
            }
            return res;
        }
    }
}

原文:求眾數[Leetcode](https://www.cnblogs.com/zhlz/p/10486072.html)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM