题目链接: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),但是在最坏情况下依然是O(n^2)。
还有另外一种解法是BM投票算法(Boyer-Moore Majority Vote algorithm),这种算法是设置一个数的计数器,在遍历数组的时候,如果是这个数,则计算器加一,不是则减一,用来计数超过一半的数非常方便。在这里我们需要进行改进一下,设置两个计数器,来统计两个数出现的次数。
如果是这两个数中的一个,则他的计算器加1,如果不是这两个数中的任何一个,则计算器都减1,如果计数器为0了,则统计当前的这个数。那么如果一个数出现次数超过1/3,则最后必然出现在统计的数中,但是我们不能确定现在得到的这两个数出现次数是否超过1/3,因此最后需要再验证一下。
代码如下:
class Solution {
public:
vector majorityElement(vector& nums) {
if(nums.size()==0) return {};
int num1, num2, cnt1=0, cnt2=0,len=nums.size();
for(auto val: nums)
{
if(num1 == val) cnt1++;
else if(num2 == val) cnt2++;
else if(cnt1==0) cnt1 = 1, num1 = val;
else if(cnt2==0) cnt2 = 1, num2 = val;
else cnt1--, cnt2--;
}
cnt1 = 0, cnt2 = 0;
for(auto val: nums)
if(val == num1) cnt1++;
else if(val == num2) cnt2++;
vector ans;
if(cnt1 > len/3.0) ans.push_back(num1);
if(cnt2 > len/3.0) ans.push_back(num2);
return ans;
}
};