寫在前沿:本文代碼均使用C語言編寫。
Description:
給定一個大小為?n?的數組,找到其中的眾數。眾數是指在數組中出現次數大于? n/2 ?的元素。
你可以假設數組是非空的,并且給定的數組總是存在眾數。
示例?1:
輸入:[3,2,3]輸出:3
示例?2:
輸入:[2,2,1,1,1,2,2]輸出:2
Analysis:
一、排序法
根據題目給定的條件,眾數定義為數組中出現次數大于N/2的元素,對數組重新排列后,位于數組N/2位置處的值就是數組的眾數。
完整C 代碼:
int majorityElement(int* nums, int numsSize) {
/*冒泡法對數組進行排序*/
? ? for (int j=1;j<numsSize;j++){
? ? for(int i=0;i<numsSize-j;i++){
? ? ? ? int temp;
? ? ? ? if(nums[i]>=nums[i+1]){
? ? ? ? ? ? temp=nums[i+1];
????????????nums[i+1]=nums[i];
? ? ? ? ? ? nums[i]=temp;
? ? ? ? }
? ? }
? ? }
? ? return nums[numsSize/2];
? ? }
總結:這種算法(簡直不好意思稱為算法)大概除了理解上簡單直白外,基本是沒有任何優點了,代碼也有一定缺陷,調用函數求個眾數順帶把原數組排序了驚不驚喜?另外這個算法LeetCode執行用時4348ms,速度是挺感人的。
二、摩爾投票算法
知乎用戶@喝七喜 在問題如何理解摩爾投票算法?中已經描述的很清楚了,另外再貼上另外一位知乎網友@JoyHao 提供的演示實例(侵刪)。由于數組中的眾數個數大于n/2,那么對數組中兩個不相等的數相互抵消,最后剩下的一個或者幾個無法再進行消除的數,就是數組中的眾數。
代碼分析:假設初始眾數(maj)為數組的第一個元素num[0],count=1,當數組后續元素等于maj時,count++,否則count--。若count=0,說明到當前及之前所有元素抵消完畢,將下一個元素重新賦值給maj,同時count=1,由下一個元素開始重新做抵消。最后剩下的maj即為眾數值。根據題目要求眾數出現次數大于n/2,因此結果必定存在,同時count必定大于0。
完整C代碼:
int majorityElement(int* nums, int numsSize) {
? ? int maj=nums[0],count=1;
? ? for (int i=1;i<numsSize;i++){
? ? ? ? if(count==0){
? ? ? ? ? ? maj=nums[i];
? ? ? ? ? ? count++;
? ? ? ? }
? ? ? ? else if(maj==nums[i]){
? ? ? ? ? ? count++;
? ? ? ? }
? ? ? ? else{
? ? ? ? ? ? count--;
? ? ? ? }
? ? }
? ? return maj;
}
總結:摩爾投票法的理解上并不會比排序法難,但是執行速度上有巨大的提升,LeetCode執行時間8ms算是一個還不錯的結果。同時這個算法還可以擴展到比如出現次數大于n/3的元素這類問題,更重要的是也不會像排序法的函數那樣給調用函數的人一點surprise。