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)