投票算法

投票算法 / Boyer-Moore算法

该算法可以用O(n)的时间复杂度和O(1)的空间复杂度找到其中的多数元素。给定一个大小为 n 的数组,多数元素是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素

1、算法步骤

需要对原数组进行两趟扫描,并且简单易实现。第一趟扫描我们得到一个候选节点candidate,第二趟扫描我们判断candidate出现的次数是否大于n/2。

第一趟扫描中,我们需要记录2个值:candidate,初值可以为任何数,第二个count,初值为0。之后,对于数组中每一个元素,首先判断count是否为0,若为0,则把candidate设置为当前元素。之后判断candidate是否与当前元素相等,若相等则count+=1,否则count-=1。如果保证数组中存在多数元素,可以不仅第二次扫描。反之不保证则需要,candidate的值没有意义。

2、原理解析

举个例子,我们的输入数组为[1,1,0,0,0,1,0],那么0就是多数元素。

首先,candidate被设置为第一个元素1,count也为1,由于1不是多数元素,所以当扫描到数组某个位置时,count一定会减为0。在我们的例子中,当扫描到第四个位置时,count变成0.

count 值变化过程:[1,2,1,0……

当count变成0时,对于每一个出现的1,我们都用一个0与其进行抵消,所以我们消耗掉了与其一样多的0,而0是多数元素,这意味着当扫描到第四个位置时,我们已经最大程度的消耗掉了多数元素。然而,对于数组从第五个位置开始的剩余部分,0依然是其中的多数元素(注意,多数元素出现次数大于n/2,而我们扫描过的部分中多数元素只占一半,那剩余部分中多数元素必然还是那个数字)。如果之前用于抵消的元素中存在非多数元素,那么数组剩余部分包含的多数元素就更多了。

类似的,假设第一个数字就是多数元素,那么当count减为0时,我们消耗掉了与多数元素一样多的非多数元素,那么同样道理,数组剩余部分中的多数元素数值不变。

这两种情况证明了关键的一点:数组中从candidate被赋值到count减到0的那一段可以被去除,余下部分的多数元素依然是原数组的多数元素。我们可以不断重复这个过程,直到扫描到数组尾部,那么count必然会大于0,而且这个count对应的candinate就是原数组的多数元素。

python(没有进行二次扫描)

def majorityElement(self, nums: List[int]) -> int:
    j, k = nums[0], 1
    for i in range(1,len(nums)):
        if k == 0:
            j = nums[i]
            k = 1
        else:
            if nums[i] == j:
                k += 1
            else:
                k -= 1
    return j

java(有二次扫描,没有复合条件的元素就返回-1)

public int majorityElement(int[] nums) {
    
    
    int j = 0;
    int k = 0;
    for(int num:nums){
    
    
        if(k==0) {
    
    
            k=1;
            j = num;
        }else{
    
    
            if(j == num) k++;
            else k--;
        }
    }
    int count = 0;
    for(int num:nums){
    
    
        if(num == j) count++; 
    }
    return count > nums.length /2 ? j:-1;
}

参考:
https://zhuanlan.zhihu.com/p/135737697
Majority Element in Parallel

https://leetcode-cn.com/problems/find-majority-element-lcci/submissions/

https://leetcode-cn.com/problems/majority-element/

猜你喜欢

转载自blog.csdn.net/weixin_42999705/article/details/114970048
今日推荐