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)