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

问题描述:

1. The majority vote problem is to determine in any given sequence of choices whether there is a choice with more occurrences than half of the total number of choices in the sequence and if so, to determine this choice. Note how this definition contrasts with the mode in which it is not simply the choice with the most occurrences, but the number of occurrences relative to the total length of the sequence. Mathematically, given a finite sequence (length n) of numbers, the object is to find the majority number defined as the number that appears more than ⌊ n/2 ⌋ times.

2. Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times. The algorithm should run in linear time and in O(1) space.


算法描述:

The algorithm is carried out in two steps:

  1. Eliminate all elements except one.
    Iterating through the  array of numbers, maintain a current candidate and a  counter initialized to 0. With the current element x in  iteration, update the counter and (possibly) the  candidate: if the counter is 0, set the current candidate to x and the counter to 1. If the counter is not 0,  increment or decrement the counter based on whether x is the current candidate.
  2. Determine if the remaining element is a valid majority element.
    With the candidate acquired in step 1, iterate through the array of numbers and count its occurrences. Determine if the result is more than half of the sequence's length. If so, the candidate is the majority. Otherwise, the sequence doesn't contain a majority.

Note that the counter can be a maximum of {\displaystyle n}n which requires {\displaystyle O(\log n)}O(\log n) space. In practice, however, a constant number of bits should suffice as a {\displaystyle 128}{\displaystyle 128} bit counter can go upto {\displaystyle 2^{128}}2^{128} which is large enough for any practical computation. The time complexity remains {\displaystyle O(n)}O(n), even considering the amount of time it takes to increment the counter because it can be incremented in constant amortized time.

算法实现:

1. Given a finite sequence (length n) of numbers, the object is to find the majority number defined as the number that appears more than ⌊ n/2 ⌋ times. 

import java.util.*;
public class MajorityVote {
    public int majorityElement(int[] num) {
        int n = num.length;
        int candidate = num[0], counter = 0;
        for (int i : num) {
            if (counter == 0) {
                candidate = i;
                counter = 1;
            } else if (candidate == i) {
                counter++;
            } else {
                counter--;
            }
        }

        counter = 0;
        for (int i : num) {
            if (i == candidate) counter++;
        }
        if (counter <= n / 2) return -1;
        return candidate;

    }
    public static void main(String[] args) {
        MajorityVote s = new MajorityVote();
        System.out.format("%d\n", s.majorityElement(new int[] {1, 2, 3}));
        System.out.format("%d\n", s.majorityElement(new int[] {2, 2, 3}));
    }
}


2. Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times. The algorithm should run in linear time and in O(1) space.

分析:
因为要找出的是出现次数大于⌊ n/3 ⌋的元素,因此最多只可能存在两个这样的元素,而且要求O(1)的空间复杂度,因此只能使用摩尔投票法。首先我们遍历一遍数组找出两个候选元素,接着再遍历一遍数组,判断候选元素的出现次数是否超过三分之一即可。我们如何确定两个候选元素呢?当有候选元素未设置时,先将当前遍历到的元素设置为候选元素。若遍历到的元素和其中一个候选元素相等时,候选元素的计数器加一,若和两个候选元素都不相等,则两个候选元素的计数器都减一。
其实摩尔投票法的本质就是将元素进行分组,每组中都是不同的元素,最后剩下的那些元素就可能是出现次数最多的元素。例如上文中的解法就是将所有元素分成若干个三元组,每组中的数字都是各不相同的。如果一个元素出现的次数超过了三分之一,那么它必然在剩下的元组中存在,因此它能成为候选元素。

public class Solution {
    public List<Integer> majorityElement(int[] nums) {
        int num1 = 0, num2 = 1;
        int count1 = 0, count2 = 0;
        for(int num: nums) {
            if (count1 == 0) {
                num1 = num;
                count1 = 1;
            } else if (num1 == num) {
                count1 ++;
            } else if (count2 == 0) {
                num2 = num;
                count2 = 1;
            } else if (num2 == num) {
                count2 ++;
            } else {
                count1 --;
                count2 --;
                if (count1 == 0 && count2 > 0) {
                    num1 = num2;
                    count1 = count2;
                    num2 = 0;
                    count2 = 0;
                }
            }
        }
        if (count1 > 0) {
            count1 = 0;
            for(int num: nums) if (num1 == num) count1 ++;
        }
        if (count2 > 0) {
            count2 = 0;
            for(int num: nums) if (num2 == num) count2 ++;
        }
        List<Integer> results = new ArrayList<>();
        if (count1*3>nums.length) results.add(num1);
        if (count2*3>nums.length) results.add(num2);
        return results;
    }
}

Reference:

1. https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_majority_vote_algorithm

2. Moore的主页上有这个算法的介绍:A Linear Time Majority Vote Algorithm 和 这个算法的一个简单示例演示,链接如下:

http://www.cs.utexas.edu/~moore/best-ideas/mjrty/index.html

3. https://leetcode.com/problems/majority-element-ii/

### 回答1: Boyer-Moore-Horspool算法是一种字符串匹配算法,它可以在文本中快速查找一个模式串。该算法的核心思想是利用模式串中的信息,尽可能地跳过不必要的比较,从而提高匹配效率。具体来说,算法首先预处理模式串,构建一个跳表,然后从文本串的末尾开始匹配,每次跳过尽可能多的字符,直到找到一个匹配位置或者到达文本串的开头。如果找到了匹配位置,则返回该位置在文本串中的下标;否则返回-1。该算法的时间复杂度为O(n+m),其中n和m分别为文本串和模式串的长度。 ### 回答2: Boyer-Moore-Horspool算法是一种用于字符串匹配的快速算法。该算法由Robert S. Boyer和J Strother Moore于1977年提出,之后由Richard Horspool进行了改进。该算法在实际应用中广泛使用,如文本编辑器中的查找和替换功能。 该算法的优点在于它能够利用模式串中的信息快速地跳过不匹配的字符。它的基本思想是从待匹配的字符串的右侧开始与模式串进行匹配,如果遇到不匹配的字符,则根据模式串中该字符的位置来确定移动的步数。这样可以在每次比较时跳过多个字符,提高了匹配的效率。 具体而言,Boyer-Moore-Horspool算法首先构建一个坏字符表,用于记录模式串中每个字符在模式串中最右出现的位置。当发生不匹配时,通过查找坏字符表获取需要移动的步数。如果坏字符不在模式串中出现,则可以直接移动模式串的长度个位置,因为整个模式串都不可能出现在待匹配的字符串中。 在匹配过程中,Boyer-Moore-Horspool算法一般比其他字符串匹配算法更快速,例如Brute-Force算法和KMP算法。但是,该算法并不能处理带有通配符或正则表达式的模式串,因此在某些特定情况下可能不适用。 总而言之,Boyer-Moore-Horspool算法是一种高效的字符串匹配算法,通过合理利用模式串中的信息,能够快速地跳过不匹配的字符,提高匹配效率。它在实际应用中有广泛的应用和成就。 ### 回答3: Boyer-Moore-Horspool算法是一种字符串匹配算法,用于在一个主字符串中查找子字符串的位置。它是Boyer-Moore算法的简化版本,由Nigel Horspool在1980年提出。 该算法的核心思想是从主字符串的末尾开始匹配,当发现不匹配的字符时,使用预先计算的"坏字符规则"和"好后缀规则"进行跳跃式的移动。坏字符规则是指对于不匹配的字符,在子字符串中查找其最右出现的位置,然后根据该位置和主字符串中当前字符的位置计算移动距离。好后缀规则是指对于匹配的子串的部分,从右往左查找其在子字符串中的最右出现位置,然后根据该位置和主字符串中当前字符的位置计算移动距离。 Boyer-Moore-Horspool算法通过在预处理阶段计算坏字符规则数组,以及在匹配阶段计算好后缀规则数组,来提高匹配的效率。算法的时间复杂度为O(n+m),其中n为主字符串的长度,m为子字符串的长度。 Boyer-Moore-Horspool算法在实际应用中具有很好的性能。它在大多数情况下比其他字符串匹配算法更快,特别是在处理长字符串和具有较小字符集的情况下。该算法已被广泛应用于文本编辑器、搜索引擎、数据压缩等领域。 总而言之,Boy er-Moore-Horspool算法是一种高效的字符串匹配算法,通过利用坏字符规则和好后缀规则进行跳跃式移动,以提高匹配效率。它在实际应用中表现出优秀的性能,是一个重要的算法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EnjoyCodingAndGame

愿我的知识,成为您的财富!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值