众数(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)

365个夜晚,我希望做到两天更一篇博客。加油,小白!
原文地址:https://www.cnblogs.com/qq2806933146xiaobai/p/13213791.html