题目链接:https://leetcode.com/problems/majority-element-ii/
Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋
times. The algorithm should run in linear time and in O(1) space.
Hint:
思路:这道题目有两种解法,第一种是基本快速排序。在快速排序中有个partition函数可以将数组两部分,左边是比这个数小的数,右边是比这个值大的数。
在这题中我们要找到出现次数超过1/3的数,那么这个数最多有两个,利用partition找出应该出现在数组1/3处,和2/3处的值,则出现超过1/3的数必然在这两个数中。然后再验证这两个数是不是解。这种解法的时间复杂度是O(n),因为要找两个数,比较麻烦。
还有另外一种解法是BM投票算法(Boyer-Moore Majority Vote algorithm),这种算法是设置一个数的计数器,在遍历数组的时候,如果是这个数,则计算器加一,不是则减一,用来计数超过一半的数非常方便。在这里我们需要进行改进一下,设置两个计数器,来统计两个数出现的次数。
如果是这两个数中的一个,则他的计算器加1,如果不是这两个数中的任何一个,则计算器都减1,如果计数器为0了,则统计当前的这个数。那么如果一个数出现次数超过1/3,则最后必然出现在统计的数中,但是我们不能确定现在得到的这两个数出现次数是否超过1/3,因此最后需要再验证一下。
边界条件:如果数组长度为1,则需要判断最后得到的两个数是否一样。
代码如下:
class Solution { public: vector<int> majorityElement(vector<int>& nums) { int cnt1 = 0, cnt2 = 0, num1, num2, len = nums.size(); if(len == 0) return result; for(int i = 0; i < len; i++) { if(cnt1 == 0) num1 = nums[i]; if(cnt2 == 0) num2 = nums[i]; if(nums[i] == num1) cnt1++; else if(nums[i] == num2) cnt2++; else { cnt1--; cnt2--; } } cnt1 = cnt2 = 0; for(int i =0; i< len; i++)//验证是否出现次数超过1/3 { cnt1 = (nums[i]==num1)?(cnt1+1):cnt1; cnt2 = (nums[i]==num2)?(cnt2+1):cnt2; } if(cnt1 > len/3.0f) result.push_back(num1); if(num1 != num2 && cnt2 > len/3.0f) result.push_back(num2); return result; } private: vector<int> result; };参考:http://www.neozone.me/leetcode229.html