Majority Element解决:Moore's Voting Algorithm

【前言】最近再刷leetcode的时候,遇到了一道关于主要元素的题目,题目如下:
Given an array of size , find the majority element. The majority element is the element that appears more than⌊ n/2 ⌋ times.You may assume that the array is non-empty and the majority element always exist in the array.

然后发现了一个类似投票的算法:A Linear Time Majority Vote Algorithm点击打开链接

算法主要解决在元素序列中找到出现次数较多的元素。

算法思想:

每次都找出一对不同的元素,从数组中删掉,直到数组为空或只有一种元素。
不难证明,如果存在元素e出现频率超过半数,那么数组中最后剩下的就只有e。

【解决思路】定义一个记录次数的数组count,count如果为0,则把改变当前候选者元素candidate,并把count设为1;否则根据当前元素e与候选者元素candidate比较来决定增加或减去count,最后的候选者元素即为所求;

候选者元素candidate即出现的count(次数)最多的元素。

When we move the pointer forward over an element e:

  • If the counter is 0, we set the current candidate to e and we set the counter to 1.
  • If the counter is not 0, we increment or decrement the counter according to whethere is the current candidate.
When we are done, the current candidate is the majority element, if there isa majority.

该题目中需要定义一个count,对应candidate出现的次数,代码如下:

         public int majorityElement3(int[] nums) {  
               if(nums.length==0)  
                   return 0;  
               int count=0;  
               int candidate=0;  
               for(int i : nums){  
                   if(candidate ==i)  
                       count++;  
                   else if(count==0){  
                       candidate =i;  
                       count=1;  
                   }  
                   else  
                       count--;  
               }  
               count=0;  
               for(int i : nums){  
                   if(i==candidate)  
                       count++;  
               }  
               return count>nums.length/2?candidate :0;     
           }  

【问题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.


该题目中需要定义一个count数组,分别对应两个candidate出现的次数(元素出现次数大于n/3,至多两个candidate),代码如下:


         /**
      * 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.
      * @param nums
      * @return
      */
     public List<Integer> majorityElement2(int[] nums) {
           /*
           A Linear Time Majority Vote Algorithm
           每次都找出一对不同的元素,从数组中删掉,直到数组为空或只有一种元素。
           不难证明,如果存在元素e出现频率超过半数,那么数组中最后剩下的就只有e。
           top 2  Majority Element (more than n/3 times.)
            */
            List<Integer> list=new ArrayList<Integer>();
            if(nums==null)
                return list;
            int[] count=new int[2];
            int[] candidate=new int[2];
            candidate[0]=0;
            candidate[1]=1;
            for(int i : nums){
                if(candidate[0]==i){
                    count[0]++;
                }
                else if(candidate[1]==i){
                    count[1]++;
                }
                else if(count[0]==0){
                    candidate[0]=i;
                    count[0]=1;
                }
                else if(count[1]==0){
                    candidate[1]=i;
                    count[1]=1;
                }
                else{
                    count[0]--;
                    count[1]--;
                }
            }
            for(int j=0;j<2;j++){
                count[j]=0;
            }
            for(int k : nums){//验证count是否满足n/3
                if(k==candidate[0])
                     count[0]++;
                else if(k==candidate[1])
                    count[1]++;
            }
            for(int l=0;l<2;l++){
                if(count[l]>nums.length/3&&!list.contains(candidate[l]))
                     list.add(candidate[l]);
            }
            return list;
        }

总结:上述算法的时间复杂度为O(n),而由于并不需要真的删除数组元素,我们也并不需要额外的空间来保存原始数组,空间复杂度为O(1)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值