Majority Vote Alogrithm 多数投票算法

来源:互联网 发布:windows 2008 开启iis 编辑:程序博客网 时间:2024/05/19 11:50

当一个序列中存在一个占大多数的的元素的时候(超过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 0
原创粉丝点击