zoukankan      html  css  js  c++  java
  • 算法 摩尔投票算法

    Boyer-Moore majority vote algorithm (摩尔投票算法)

    典型案例:

    (1) 找出大于n/2的元素,leetcode: https://leetcode.com/problems/majority-element/ 

    class Solution {
        public int majorityElement(int[] nums) {
            int count = 0;
            int cur = 0;
            for(int i = 0; i < nums.length; ++i){
                if(count == 0){
                    cur = nums[i];
                    count++;
                }else{
                    if(nums[i] == cur){
                        count++;
                    }else{
                        count--;
                    }
                }
            }
            return cur;
        }
    }

    (2) 找出大于n/3的元素, letcode: https://leetcode.com/problems/majority-element-ii/

    /*
        思路:摩尔投票升级版,超过n/3的数最多只能有两个;
        先选出两个候选人A,B,遍历数组,如果投A(等于A),则A的票数++;如果投B,B的票数++;
        如果A,B都不投(即与A,B都不相等),那么检查此时是否AB中候选人的票数是否为0,如果为0,则成为新的候选人;
        如果A,B两个人的票数都不为0,那么A,B两个候选人的票数均--;
        遍历结束后选出两个候选人,但是这两个候选人是否满足>n/3,还需要再遍历一遍数组,找出两个候选人的具体票数
         */
        public List<Integer> majorityElement(int[] nums) {
            if (nums==null||nums.length==0){
                return null;
            }
    
            //初始化,定义两个候选人以及对应的票数
            int candidateA=nums[0];
            int candidateB=nums[0];
            int countA=0;
            int countB=0;
    
            // 遍历数组
            for (int num:nums){
                if (num==candidateA){ //投A
                    countA++;
                    continue;
                }
    
                if (num==candidateB){// 投B
                    countB++;
                    continue;
                }
                //此时A,B都不投,检查是否有票数为0情况,如果为0,则更新候选人
                if (countA==0){
                    candidateA=num;
                    countA++;
                    continue;
                }
    
                if (countB==0){
                    candidateB=num;
                    countB++;
                    continue;
                }
    
                //此时两个候选人的票数都大于1,且当前选名不投AB,那么A,B对应的票数都要--;
                countA--;
                countB--;
            }
    
            // 上一轮遍历找出了两个候选人,但是这两个候选人是否均满足票数大于N/3仍然没法确定,需要重新遍历,确定票数
            countA=0;
            countB=0;
    
            for (int num:nums){
                if (num==candidateA){
                    countA++;
                }else if (num==candidateB){
                    countB++;
                }
            }
    
            List<Integer> resultList=new ArrayList<>();
    
            if (countA>nums.length/3){
                resultList.add(candidateA);
            }
    
            if (countB>nums.length/3){
                resultList.add(candidateB);
            }
    
            return resultList;
        }

    Boyer-Moore majority vote algorithm(摩尔投票算法)是一种在线性时间O(n)和空间复杂度的情况下,在一个元素序列中查找包含最多的元素。它是以Robert S.Boyer和J Strother Moore命名的,1981年发明的,是一种典型的流算法(streaming algorithm)。

    在它最简单的形式就是,查找最多的元素,也就是在输入中重复出现超过一半以上(n/2)的元素。如果序列中没有最多的元素,算法不能检测到正确结果,将输出其中的一个元素之一。

    当元素重复的次数比较小的时候,对于流算法不能在小于线性空间的情况下查找频率最高的元素。

    假设这个数组中共有n个元素,我们可以把数值不同的元素看做不同的群体成员(一个数字代表一个群体)。那么我们现在要根据每个群在这个名单中各自的人数,使得在名单中出现人数最多的那个管理群。我们就先从数组的第一个元素开始,假定它代表的群体的人数是最多的,那么根据数组中出现次数超过一半的数只有一个的特质,如果我们设置一个计数器,在遍历时遇到不同于这个群体的人时就将计数器-1,遇到同个群体的人时就+1,只要在计数器归0时就重新假定当前元素代表的群体为人数最多的群体再继续遍历(此时数据被分为两段,前一段数据中被计数的元素数和numbers except it 数量是相等的,而后面的data中又满足词频最高的数大于总数一半的情形,有点分治策略的思想),那么到了最后,计数器记录的那个群体必定是人最多的那个群体。这里就使得元素排序是不会造成任何影响的,只关心元素的个数所带来的对于计数器+1或-1的影响。

    算法实现:

    法在局部变量中定义一个序列元素(m)和一个计数器(i),初始化的情况下计数器为0. 算法依次扫描序列中的元素,当处理元素x的时候,如果计数器为0,那么将x赋值给m,然后将计数器(i)设置为1,如果计数器不为0,那么将序列元素m和x比较,如果相等,那么计数器加1,如果不等,那么计数器减1。处理之后,最后存储的序列元素(m),就是这个序列中最多的元素。

    典型的案例

    (1)找出大于n/2的元素

    (2)找出大于n/3的元素把两个数转化为一个数的思想,两个大于n/3的肯定大于一半
    ---------------------
    作者:码农张学友
    来源:CSDN
    原文:https://blog.csdn.net/dpengwang/article/details/81710259
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    octotree神器 For Github and GitLab 火狐插件
    实用篇如何使用github(本地、远程)满足基本需求
    PPA(Personal Package Archives)简介、兴起、使用
    Sourse Insight使用过程中的常使用功能简介
    Sourse Insight使用教程及常见的问题解决办法
    github 遇到Permanently added the RSA host key for IP address '192.30.252.128' to the list of known hosts问题解决
    二叉查找树的C语言实现(一)
    初识内核链表
    container_of 和 offsetof 宏详解
    用双向链表实现一个栈
  • 原文地址:https://www.cnblogs.com/frankcui/p/10474223.html
Copyright © 2011-2022 走看看