面试题 17.10. 主要元素
摩尔投票:依次将两个不同元素删除/抵消,这样剩下的元素数量就可能会是比数组中所有元素数量的一半都大。
这里的可能是有些情况比如:1212333,这个数列依次抵消剩下333,这个3的数量显然没有该数列长度的一般。而被抵消的数可以确保一定不会比数列长度的一半还大(我认为摩尔投票利用的数学原则就是这个)。
总结:摩尔投票可以保证被抵消的元素一定不会是主要元素,而剩下的元素的数量可能是会占据数组数量的一半以上的。
理清楚这个思想,那么对于这道题就轻松了,可以先设置一个变量n来存放可能会是数组中元素数量最多的元素。sum来存放当前该元素拥有的数量。
- 首先是从头到尾遍历一次数组
- 判断sum是否为0;如果是0,则将当前元素作为可能是数组中元素数量最多的那个,n=sum[i];若不是,则保留n。
- 判断n与当前元素是否相等,不想等则sum-1表示抵消一次候选元素n的数量,相等就加一。
到这里得出来的n是经过摩尔投票后抵消剩余的元素,sum保存的也是抵消后的数量,所以要再次用一个循环统计所有n出现的次数。
最终用统计的数量sum与nums.length/2进行比较,判断是否是主要元素。
代码如下:
var majorityElement = function(nums) {
let n=-1 ;
let sum =0;
for(let i=0;i<nums.length;i++){
n = sum==0?nums[i]:n
sum = n==nums[i]?sum+1:sum-1
}
sum=0
for(let i =0;i<nums.length;i++){
sum= n==nums[i]?sum+1:sum
}
return sum>nums.length/2?n:-1
};