投票算法
因为这两道题涉及到投票算法的思想,所以先从什么是投票算法入手。
Boyer-Moore majority vote algorithm(摩尔投票算法)是一种在线性时间O(n)和空间复杂度的情况下,在一个元素序列中查找包含最多的元素。
在它最简单的形式就是,查找最多的元素,也就是在输入中重复出现超过一半以上(n/2)的元素。如果序列中没有最多的元素,算法不能检测到正确结果,将输出其中的一个元素之一。
当元素重复的次数比较小的时候,对于流算法不能在小于线性空间的情况下查找频率最高的元素。
算法描述
算法在局部变量中定义一个序列元素(m)和一个计数器(i),初始化的情况下计数器为0. 算法依次扫描序列中的元素,当处理元素x的时候,如果计数器为0,那么将x赋值给m,然后将计数器(i)设置为1,如果计数器不为0,那么将序列元素m和x比较,如果相等,那么计数器加1,如果不等,那么计数器减1。处理之后,最后存储的序列元素(m),就是这个序列中最多的元素。
如果不确定是否存储的元素m是最多的元素,还可以进行第二遍扫描判断是否为最多的元素。
输出元素出现次数大于n/2的数代码:class Solution {
public:
// moore majority vote algorithm
int majorityElement(vector<int>& nums) {
int cand;
int count = 0;
for (int i = 0; i < nums.size(); i++) {
if (count == 0) {
cand= nums[i];
count++;
} else if (nums[i] == cand) {
count++;
} else
count--;
}
return cand;
}
};
还有一种通用的情况:
输出元素出现次数大于n/k的数
思路:需要维持一个长度为k-1的候选者数组及统计数组。如果候选者数组没有满,将其加入,相应的统计数计为1,如果在候选数组中出现过,将其计数加1,如果没有出现,将所有的计数减1
class Solution
{
private:
vector<int> majorityElement(vector<int>& nums, int k)
{
int cnt = k - 1;
vector<int> candidates(cnt, 0);
vector<int> count(cnt, 0);
for (int num : nums)
{
bool found = false;
for (int i = 0; i < cnt; i++)
{
if (!count[i] || num == candidates[i])
{
count[i]++;
candidates[i] = num;
found = true;
break;
}
}
if (!found)
{
for (int i = 0; i < cnt; i++)
{
count[i]--;
}
}
}
for (int i = 0; i < cnt; i++)
{
count[i] = 0;
}
for (int num : nums)
{
for (int i = 0; i < cnt; i++)
{
if (num == candidates[i])
{
count[i]++;
break;
}
}
}
vector<int> ans;
for (int i = 0; i < cnt; i++)
{
if (count[i] > nums.size() / k) ans.push_back(candidates[i]);
}
return ans;
}
};
Majority Element I
这一题就是上面投票算法:输出元素出现次数大于n/2的数
时间O(n) 空间 O(1)
C++ AC代码:
class Solution {
public:
int majorityElement(vector<int>& nums) {
int len = nums.size();
int variable;
int times=0;
for(int i=0;i<len;i++){
if(times==0){
variable=nums[i];
}
if(variable==nums[i])
times++;
else
times--;
}
return variable;
}
};
Majority Element II
这一题就是上面投票算法:使用通用输出元素出现次数大于n/k的数
时间O(n) 空间 O(1)
C++ AC代码:
class Solution {
public:
vector<int> majorityElement(vector<int>& nums) {
int len = nums.size();
int cnt = 2;
vector<int> cand(cnt,-1);
vector<int> count(cnt,0);
vector<int> res;
for(int i=0;i<len;i++){
bool found = false;
for(int j=0;j<cnt;j++){
if(cand[j]==nums[i]){
count[j]++;
cout<<nums[i]<<" "<<cand[j]<<" "<<count[j]<<endl;
found = true;
break;
}
}
for(int j=0;j<cnt;j++){
if(!count[j]&&!found){
count[j]++;
cand[j] = nums[i];
cout<<nums[i]<<" "<<cand[j]<<" "<<count[j]<<endl;
found = true;
break;
}
}
if(!found){
cout<<nums[i]<<endl;
for(int j=0;j<cnt;j++)
count[j]--;
}
}
for(int i=0;i<cnt;i++)
count[i]=0;
for(int i=0;i<len;i++){
for(int j=0;j<cnt;j++){
if(cand[j]==nums[i]){
count[j]++;
break;
}
}
}
for(int i=0;i<cnt;i++){
cout<<cand[i]<<endl;
if(count[i]>len/(cnt+1))
res.push_back(cand[i]);
}
return res;
}
};