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

posted @   ꧁执笔小白꧂  阅读(1999)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏
· Manus爆火,是硬核还是营销?
点击右上角即可分享
微信分享提示