LeetCode:Majority Element I II 投票算法

投票算法

因为这两道题涉及到投票算法的思想,所以先从什么是投票算法入手。

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;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值