摩尔投票法(力扣- -229. 求众数 II)
摩爾投票法(力扣- -229. 求眾數 II)
文章目錄
- 摩爾投票法(力扣- -229. 求眾數 II)
- 一、題目描述
- 二、分析
- 摩爾投票法
- 總結
- 三、代碼
一、題目描述
二、分析
- 這道題如果用O(N)O(N)O(N)的空間復雜度來解決是非常簡單的,但是題目要求:嘗試設計時間復雜度為 O(n)、空間復雜度為 O(1)的算法解決此問題。
- 這里介紹摩爾投票法
摩爾投票法
-
摩爾投票法,解決的問題是如何在任意多的候選人中,選出票數超過一半的那個人。注意,是超出一半票數的那個人。
-
假設投票是這樣的,[A, C, A, A, B](ABC 是指三個候選人)。
-
第一張票與第二張票進行對坑,如果票不同則互相抵消掉;
-
接著第三票與第四票進行對坑,如果票相同,則增加這個候選人的可抵消票數;
-
這個候選人拿著可抵消票數與第五張票對坑,如果票不同,則互相抵消掉,即候選人的可抵消票數 -1。
-
圖解
看完上面的圖片之后,相信已經理解摩爾投票法是如何選取一個最有希望的候選人的。
-
豬豬豬豬豬豬意:
-
上面最后得道的結果并不意味著這個候選人的票數一定能超過一半,例如 [A, B, C] 的抵消階段,最后得到的結果是 [C,1],C 候選人的票數也未能超過一半的票數。
-
這里有一個優化,如果最后得到的可抵消票數是 0 的話,那他已經無緣票數能超過一半的那個人了。因為本來可能有希望的,但是被后面的一張不同的票抵消掉了。所以,在這里可以直接返回結果,無需后面的計算了。
-
如果最后得到的抵消票數不為 0 的話,那說明他可能希望的,這是我們需要一個階段來驗證這個候選人的票數是否超過一半—— 計數階段。
-
所以摩爾投票法分為兩個階段:抵消階段和計數階段。
-
抵消階段:兩個不同投票進行對坑,并且同時抵消掉各一張票,如果兩個投票相同,則累加可抵消的次數;
-
計數階段:在抵消階段最后得到的抵消計數只要不為 0,那這個候選人是有可能超過一半的票數的,為了驗證,則需要遍歷一次,統計票數,才可確定。
-
摩爾投票法經歷兩個階段最多消耗 O(2n)O(2n)O(2n) 的時間,也屬于 O(n)O(n)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] 。
-
圖解
總結
-
看完圖片之后,是不是理解了,是不是也清晰了。
-
如果至多選一個代表,那他的票數至少要超過一半(?1/2?)(? 1/2 ?)(?1/2?)的票數;
-
如果至多選兩個代表,那他們的票數至少要超過(?1/3?)(? 1/3 ?)(?1/3?) 的票數;
-
如果至多選m個代表,那他們的票數至少要超過 (?1/(m+1)?)(? 1/(m+1) ?)(?1/(m+1)?)的票數。
所以以后碰到這樣的問題,而且要求達到線性的時間復雜度以及常量級的空間復雜度,直接套上摩爾投票法
三、代碼
class Solution { public:vector<int> majorityElement(vector<int>& nums) {if(nums.empty()){return {};}//題目求的是滿足元素個數大雨n / 3的元素,空間復雜度為O(1)//所以只需要按摩爾投票法記錄2個元素的抵消個計數情況即可//第一個元素及票數情況int target1 = nums[0];int count1 = 0;//第二個元素及票數情況int target2 = nums[0];int count2 = 0;//遍歷for(auto& e : nums){//如果和記錄的元素中有相等的情況,更新他的計數if(e == target1){count1++;continue;}else if(e == target2){count2++;continue;}//程序走到這里代表沒有和記錄的元素相等的情況,代表//需要進行抵消操作//在進行抵消之前需要判斷記錄的元素是否有為0情況,因為如果為0//需要更新記錄的元素if(count1 == 0){target1 = e;count1++;continue;}else if(count2 == 0){target2 = e;count2++;continue;}//抵消count1--;count2--;}//再對有可能滿足情況的標記元素進行一次計數,進行驗證int val1 = 0;int val2 = 0;for(auto& e : nums){if(e == target1){val1++;}else if(e == target2){val2++;}}vector<int> ret;if(val1 > nums.size() / 3){ret.emplace_back(target1);}if(val2 > nums.size() / 3){ret.emplace_back(target2);}return ret;} };總結
以上是生活随笔為你收集整理的摩尔投票法(力扣- -229. 求众数 II)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 优化传输文件的性能- -零拷贝
- 下一篇: 力扣- -241.为运算表达式设计优先级