面试题17.10. 主要元素:Boyer-Moore Majority Vote Algorithm

又是感冒的一天,完全看不下去任何东西,就来刷算法题了…
首先来看看题目:

数组中占比超过一半的元素称之为主要元素。给定一个整数数组,找到它的主要元素。若没有,返回-1。

示例 1:
输入:[1,2,5,9,5,9,5,5,5] 输出:5
示例 2:
输入:[3,2] 输出:-1
示例 3:
输入:[2,2,1,1,1,2,2] 输出:2

看到这道题我的第一想法还是做Hash计数,但是数组最大元素不确定,这时候很难开辟一个合适大小的数组。

写这篇文章还是为了记录一种之前没学过的算法(菜哭了orz):Boyer-Moore Majority Vote Algorithm,又叫多数投票算法

首先给出最终代码:

class Solution {
    
    
public:
    int majorityElement(vector<int>& nums) {
    
    
        int Counter = 0;
        int MajorElement;
        int AppearTimes = 0;
        //查找此数组中出现最多次的元素
        for(auto PresentElement : nums)
            if(Counter == 0)
            {
    
    
                MajorElement = PresentElement;
                Counter++;
            }
            else
                if(MajorElement == PresentElement)
                    Counter++;
                else
                    Counter--;

        //确定此元素出现的次数大于nums.size() / 2, 那么它也就是主要元素
        if(Counter > 0) 
            for(auto PresentElement : nums)
                if(PresentElement == MajorElement)
                    AppearTimes ++;
        
        if(AppearTimes > nums.size() / 2)
            return MajorElement;
        else
            return -1;

    }
};

多数投票算法可以在O(n)的时间复杂度,O(1)的空间复杂度中找出数组中的多数元素。
事实上,上面的代码中只有这一部分是多数投票算法:

 for(auto PresentElement : nums)
            if(Counter == 0)
            {
    
    
                MajorElement = PresentElement;
                Counter++;
            }
            else
                if(MajorElement == PresentElement)
                    Counter++;
                else
                    Counter--;

它的本质其实就是元素之间的相互抵消,下面我想谈一谈我对这个算法的理解,为以后复习做一个助记。

  1. 这种抵消包含了假设,MajorElement = PresentElement是一种假设,此后所有的判断都基于MajorElement是多数元素的前提来进行。
  2. 我们的目的是找多数元素,所以不要囿于元素的具体数值。在1的假设下,此后所有元素的判断都被抽象成不是多数元素。
  3. 如果和当前假定的元素相同,那么假设得到了增强,计数值+1
  4. 如果和当前假定的元素不同,那么假设得到了削弱,计数值-1,注意这种削弱是相互的
  5. 对4中相互削弱做一个解释,假设当前MajorElement = 5且Counter = 2, 如果下一个遍历到的数组元素是6,那么是应该将Counter - 1 = 1表示5作为多数元素的假设得到了削弱,反过来,循环会直接读取下一个元素,表示6我们也不再考虑了,它也被假设的多数元素5削弱了。正是这种削弱的相互性,使得MajorElement的寻找可以通过一次遍历完成。

End Of Blog

猜你喜欢

转载自blog.csdn.net/zzy980511/article/details/111220338
今日推荐