摩尔投票算法

Boyer-Moore majority vote algorithm(摩尔投票算法)是一种线性时间复杂度和常数级空间复杂度的算法,用来查找元素序列中的众数。它是用Robert S. Boyer和J Strother Moore两人的名字命名,是一种典型的流算法。

该算法的最简单的形式,查找最多出现的元素,也就是找到一个输入中出现一半以上的重复元素。但是,如果该数不存在的话,算法将检测不到真实结果,但是仍将输出输入元素中的一个元素。 但是,我们可以再次遍历输入序列,计算返回元素出现的次数,以确定它是否真的是众数。

该算法在其局部变量中维护一个临时变量m和一个计数器c,计数器初值为零。 然后我们遍历序列中的每个元素。如果c==0,则m=x;c=1;(其中x表示我们遍历到的元素)。 如果m==x,那么c++,否则c--。 最后返回m即可。

这可以用伪代码表示为以下步骤:

  • 初始化一个元素m和一个计算器c=0
  • 对于输入序列中的每个元素x
    • 如果i == 0, 那么 m = x 并且 i = 1
    • 如果m == x, 那么c++,否则的话c--
  • 返回m

举个例子:

[ 1 1 1 2 2 3 1] m = 0, c = 0
[*1 1 1 2 2 3 1] m = 1, c = 1
[1 *1 1 2 2 3 1] m = 1, c = 2
[1 1 *1 2 2 3 1] m = 1, c = 3
[1 1 1 *2 2 3 1] m = 1, c = 2
[1 1 1 2 *2 3 1] m = 1, c = 1
[1 1 1 2 2 *3 1] m = 1, c = 0
[1 1 1 2 2 3 *1] m = 1, c = 1

实际上这个过程类似于栈。当我们碰到第一个元素1,我们将他压入栈中

stack: 1

接着碰到一系列1,持续压栈,就变成了

stack: 1 1 1

当我们碰到2,此时2和栈顶元素1不同,所以我们需要弹出栈顶元素,同时这个2也不需要压栈。 后面的元素操作同理,最后返回栈顶元素。这样我们只通过mc两个元素模拟了栈操作。

class Solution 
{
public:
    /*
     * @param nums: a list of integers
     * @return: find a  majority number
     */
    int majorityNumber(vector<int> &nums) 
    {
        int c = 0, m = nums[0];
        for (auto num : nums)
        {
            if (c == 0)
            {
                m = num; ++c;
            }
            else if (m == num) ++c;
            else --c;
        }
        // check if there is a majority
        int counter = 0;
        for (auto num : nums) 
        {
            if (num == m) counter++;
        }
        if (counter < (nums.size() + 1) / 2) return -1;        
        return m;
    }
};

reference:

https://en.wikipedia.org/wiki/Boyer–Moore_majority_vote_algorithm

https://helloacm.com/data-structures-algorithms-series-majority-number-boyer-moore-majority-vote-algorithm/

你可能感兴趣的:(Data,Structures,and,Algorithms,摩尔投票算法)