統計一批學生的平均成績與不及格人數
阿新 • • 發佈:2021-10-10
目錄
229. 求眾數 II
思路
方法一:雜湊統計
用雜湊統計陣列中每個元素出現的次數。
方法二:摩爾投票法
摩爾投票法:摩爾投票法的核心思想為對拼消耗。首先我們考慮最基本的摩爾投票問題,比如找出一組數字序列中出現次數大於總數一半的數字(並且假設這個數字一定存在)。我們可以直接利用反證法證明這樣的數字只可能有一個。
假設投票是這樣的,[A, C, A, A, B],ABC 是指三個候選人。
- 第一張票與第二張票進行對坑,如果票不同則互相抵消掉;
- 接著第三票與第四票進行對坑,如果票相同,則增加這個候選人的可抵消票數;
- 這個候選人拿著可抵消票數與第五張票對坑,如果票不同,則互相抵消掉,即候選人的可抵消票數 -1。
摩爾投票法分為兩個階段:抵消階段和計數階段。
- 抵消階段:兩個不同投票進行對坑,並且同時抵消掉各一張票,如果兩個投票相同,則累加可抵消的次數;
- 計數階段:在抵消階段最後得到的抵消計數只要不為 0,那這個候選人是有可能超過一半的票數的,為了驗證,則需要遍歷一次,統計票數,才可確定。
摩爾投票法經歷兩個階段最多消耗 O(2n) 的時間,也屬於 O(n) 的線性時間複雜度,另外空間複雜度也達到常量級。
本題是在任意多的候選人中,選出票數超過⌊ 1/3 ⌋的候選人。可以這樣理解,假設投票是這樣的 [A, B, C, A, A, B, C],ABC 是指三個候選人。
- 第 1 張票,第 2 張票和第3張票進行對坑,如果票都不同,則互相抵消掉;
- 第 4 張票,第 5 張票和第 6 張票進行對坑,如果有部分相同,則累計增加他們的可抵消票數,如 [A, 2] 和 [B, 1];
- 接著將 [A, 2] 和 [B, 1] 與第 7 張票進行對坑,如果票都沒匹配上,則互相抵消掉,變成 [A, 1] 和 [B, 0] 。
程式碼
class Solution { public List<Integer> majorityElement(int[] nums) { // 建立返回值 List<Integer> res = new ArrayList<>(); if (nums == null || nums.length == 0) return res; // 初始化兩個候選人candidate,和他們的計票 int cand1 = nums[0], count1 = 0; int cand2 = nums[0], count2 = 0; // 摩爾投票法,分為兩個階段:配對階段和計數階段 // 配對階段 for (int num : nums) { // 投票 if (cand1 == num) { count1++; continue; } if (cand2 == num) { count2++; continue; } // 第1個候選人配對 if (count1 == 0) { cand1 = num; count1++; continue; } // 第2個候選人配對 if (count2 == 0) { cand2 = num; count2++; continue; } count1--; count2--; } // 計數階段 // 找到了兩個候選人之後,需要確定票數是否滿足大於 N/3 count1 = 0; count2 = 0; for (int num : nums) { if (cand1 == num) count1++; else if (cand2 == num) count2++; } if (count1 > nums.length / 3) res.add(cand1); if (count2 > nums.length / 3) res.add(cand2); return res; } }