摩尔投票法

194 阅读2分钟

摩尔投票法

1.原理

1.1形象化描述

会议大厅站满了投票代表,每个都有一个牌子上面写着自己所选的候选人的名字。然后选举意见不合的(所选的候选人不同)两个人,会打一架,并且会同时击倒对方。显而易见,如果一个人拥有的选票比其它所有人加起来的选票还要多的话,这个候选人将会赢得这场“战争”,当混乱结束,最后剩下的那个代表(可能会有多个)将会来自多数人所站的阵营。但是如果所有参加候选人的选票都不是大多数(选票都未超过一半),那么最后站在那的代表(一个人)并不能代表所有的选票的大多数。因此,当某人站到最后时,需要统计他所选的候选人的选票是否超过一半(包括倒下的),来判断选票结果是否有效

1.2算法步骤

对抗阶段

设立一个计数器cnt=0。不断去判断数组中的元素,如果cnt=0,则将当前元素加入阵营,cnt++.反之cnt>0,则需判断是否属于同一阵营,是则+不是则-;

统计阶段

最后剩余的阵容的候选人,不一定就是人数最多的(可能不存在主元素,群雄乱战),则还需要判断该阵营人数是否>总人数的一半。

1.3伪代码

QQ截图20230214195159.png

2.例题及代码

eg. leetcode 面试 17.10 :求一维数组中存在主元素(主元素是指该元素在数据出现个数m超过数组长度的一半 m>n/2)

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        //摩尔投票法
        int cnt=1,n=nums.size();
        int mainElem=nums[0];//统计数量 初始化为数组首个字母
        for(int i=1;i<n;i++){
            if(nums[i]==mainElem)
                cnt++;
            else
                if(cnt>0){
                    cnt--;
                }
                else{
                    mainElem=nums[i];
                    cnt++;
                }
        }

        //判断之后还得统计元素个数是否大于一半 !剩下的元素 如果个数大于一半,肯定就主元素
        if(cnt>0){
            cnt=0;
            for(auto num :nums){
                if(num==mainElem)
                cnt++;
            }
        }
        if(cnt>(n/2))return mainElem;
        return-1;
    }
};