Majority Vote Alogrithm 多数投票算法

当一个序列中存在一个占大多数的的元素的时候(超过50%),该算法可以在O(1)空间和O(n)时间内找出这个元素。

  • Tips: ⌊ 59/60⌋ = 0, floor(),向下取整

Majority Element

Given an array of size n, 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.

Majority Element II

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.

Analysis

大致思路就是,比如超过数组一半元素以上的element,可以每次从数组删除2个不一样的元素,那么最后剩下的一定就是major element。
超过 ⌊ n/3 ⌋,那就每次从数组里面删除三个不一样的元素。

Code

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

        }
        return target;
    }
}
Majority Element II

思路依然同 Majority Element 一样,不同的是我们需要两个 Majority Element 的候选者,同时需要两个 count 分别对候选者进行计数。
count 为 candidate 当前出现的次数。count == 0 说明当前 candidate 对应的候选者已经被移除,我们需要设定一个新的候选者。

public class Solution {
    public List<Integer> majorityElement(int[] nums) {
        List<Integer> result = new ArrayList<Integer>();
        int count1 = 0, count2 = 0;
        int target1 = 0 ,target2 = 1;
        for(int i=0; i<nums.length; i++){
            if(nums[i]==target1){//当前数字等于1号候选数字
                count1++;
            }
            else if(nums[i]==target2){//当前数字等于2号候选数字
                count2++;
            }
            else if(count1==0){ //当前数字不等于1,2号候选数字,且1号候选数字可以被重新选择
                count1++;
                target1 = nums[i];
            }
            else if(count2==0){//当前数字不等于1,2号候选数字,且2号候选数字可以被重新选择
                count2++;
                target2 = nums[i];
            }
            else{//删除三个互相不一样的元素
                count1--; 
                count2--;
            }

        }
        count1 = 0;
        count2 = 0;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] == target1)
                count1++;
            else if (nums[i] == target2)
                count2++;
        }
        if (count1 > nums.length / 3)
            result.add(target1);
        if (count2 > nums.length / 3)
            result.add(target2);
        return result;
    }
}

一些思考

以下部分via Majority Vote Alogrithm(最大投票算法)及其扩展

问题一: if 的判定顺序有要求吗?如果有要求的话应该是怎么样的呢?

答案是有要求,细心的读者可能发现,在 Majority Element 中,我们对 count == 0 的判断在对 candidate == nums[i] 的判断之前,而在 Majority Element II 中则正好相反。

这是因为,count == 0 是用来判断对应 candidate 的当前存活量,在判断这一步之前,我们必须确保数组中当前数字不等于 两个 candidate中的任意一个。否则,我们可能会在 count0!=0 && count1==0 && nums[i]==candidate0 时错误的将 nums[i] 赋值给 candidate1。

问题二:这里给 candidate0 candidate1 初始化值为 0,这会不会影响我们运行的结果?

不会,因为 candidate0 只会在第一次循环中使用,如果 candidate0 == nums[0],count++不会引起任何问题。如果 candidate != nums[0] 那么我们此时 count==0 重新初始化 candidate0 == nums[0],同样不会有任何影响。

问题二扩充:如果我们初始化 int candidate0 = 0, candidate1 = 1 会不会影响我们的运行结果呢?

问题三:这里能够省略 distinct() 吗?为什么?

不能,尽管我们在循环中首先通过 if(candidate0 == nums[i]) 和 else if(candidate1 == nums[i]) 两个 if 判断,使得 candidate0 != candidate1 在绝大部分下成立,但是在一种极为特殊的情况下仍然可能会使得我们得到重复的数组。

试想当整个数组所有的数字都相等的时候,我们 candidate0 和 candidate1 这两个候选数字中,有一个数字将永远不会被重新赋值,也就是说,有一个数字将我们赋给的初值保持到了最后。

在我们的代码中,因为我们将两个候选数字都初始化 0,所以当数组 全为0 时会返回错误的结果。

这一点,我们可以通过将两个候选数字初始化为不同的数字来解决:int candidate0 = 0,candidate1 = 1,这样我们就可以移除掉 distinct() 了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值