摩尔排序应用于唱票选代表
条件 :选最多m个人且他的票数必须是超过总数的m+1分之一的票数
时间复杂度:线性 空间复杂度:常数级
例:选2个人(票数大于1/3)
正确性:相互抵消票数 遇到3个不同的票数才相互抵消 因此至多抵消(n/3)次
而候选人的票数必须大于n/3 因此剩下的肯定是候选人
实现:两个候选人设为peo1=nums[0] peo2=nums[0]
count1=count2=0
从头开始遍历vector(记住每次都是三个不同的人互相抵消)
1:如果当前的是peo1 那么count1++
2:如果当前的是peo2 那么count2++
3:如果当前的不是peo1或peo2 并且count1和count2都不为0 那么三者互相抵消
count1--,count2--
4:如果当前的不是peo1或peo2 并且count1为0 count2不为0 那么peo1替换成当前的nums[i],count1++
5:如果当前的不是peo1或peo2 并且count2为0 count1不为0 那么peo2替换成当前的nums[i],count2++
最后再确认一下peo1和peo2是否是就ok了
例题:
给定一个大小为 n 的整数数组,找出其中所有出现超过 ⌊ n/3 ⌋ 次的元素。
示例 1:
输入:[3,2,3]
输出:[3]
示例 2:
输入:nums = [1]
输出:[1]
示例 3:
输入:[1,1,1,3,3,2,2,2]
输出:[1,2]
提示:
1 <= nums.length <= 5 * 104
-109 <= nums[i] <= 109
进阶:尝试设计时间复杂度为 O(n)、空间复杂度为 O(1)的算法解决此问题。
class Solution {
public:
vector<int> majorityElement(vector<int>& nums) {
vector<int>v;
if(nums.empty())return v;
int peo1=0,peo2=0;
int count1=0,count2=0;
//就记住一点:每次抵消三个不同的人的票数
for(int i=0;i<nums.size();i++)
{
if(peo1==nums[i])
{
count1++;
}
else if(peo2==nums[i])
{
count2++;
}else if(count2&&count1) //两个count都不为零 这个时候可以同时消掉3个不同的
{
count1--;
count2--;
}else if(!count1) //peo2的count为0了 那么当前nums[i]的可以作为peo2(替补上去)
{
peo1=nums[i];
count1++;
}else {
peo2=nums[i];
count2++;
}
}
//确认一下:
count1=0,count2=0;
for(int each:nums)
{
if(each==peo1)
{
count1++;
}else if(each==peo2)
{
count2++;
}
}
if(count1>nums.size()/3)v.push_back(peo1);
if(count2>nums.size()/3)v.push_back(peo2);
return v;
}
};