leetcode-Majority Element

AC代码(投票算法基础版)
class Solution {
public int majorityElement(int[] nums) {
int count = 0;
int candiadate = 0;
for(int i : nums)
{
if(count == 0) {
count++;
candiadate = i;
}
else if(i == candiadate)
count++;
else count--;
}
return candiadate;
}
}
Boyer-Moore投票算法(基础版)
- 用于求解上述主要元素问题,即数组中出现此时大于一半多的元素。
- INTUITION:维护一个候选candiate,当遇到是candiate值得时候计数器增加,当遇到不是candiate的时候计数器减1.当计数器减到0时更换candiate。最后返回的candiate即为候选值。
- 由于count=0时才会设置candiate,因此我们证明最后一次count=0时,进入循环,设置的candiate一定是这个主要元素。
- 如果不是这个主要元素,那么这最后一次从count == 0到退出循环,最终有count>=0 ,且这最后一部分candidate(不是要找的主要元素)出现的次数一定比一半还多(否则就不是最后一次count =0时进入循环),且这个candidate出现的次数最少为1次。从整个序列中除去最后一部分所有的candidate,元素最多剩下n-1个。一般的,如果假设最后一部分元素有k个,那么candidate至少出现的次数是⌈k/2⌉\lceil k/2 \rceil⌈k/2⌉次(分最后一部分总个数为奇数和偶数讨论),否则这不是最后一次进入循环时的count = 0。如果这最后一部分剩余的元素都是主要元素,给出了主要元素在最后一部分的最多个数为k−⌈k/2⌉k - \lceil k/2 \rceilk−⌈k/2⌉。
- 显然前面部分所有的元素为n - k个。
- 由于前面的每一个部分,都是在count = 0进入循环重新候选,再次count=0时结束这个部分,根据算法流程,显然每个部分的数量都是偶数(所以前面所有部分的元素个数总和为偶数
- 同时,前面每一部分的candiadate都在每个部分中恰好出现一半。如果这些candiate都是我们要求的主要元素,那么在前面所有部分这些主要元素出现的次数为n−k2\frac{n - k}{2}2n−k次。
- 于是主要元素出现总次数的最大值次数为k−⌈k/2⌉+n−k2=n+k2−⌈k/2⌉k - \lceil k/2 \rceil +\frac{n - k}{2}=\frac{n+k}{2}- \lceil k/2 \rceilk−⌈k/2⌉+2n−k=2n+k−⌈k/2⌉
- 考虑关系:n+k2−⌈k/2⌉≤n+k2−k2=n2<⌊n2⌋+1\frac{n+k}{2}- \lceil k/2 \rceil \leq \frac{n+k}{2} - \frac{k}{2} = \frac{n}{2} < \lfloor \frac{n}{2} \rfloor + 12n+k−⌈k/2⌉≤2n+k−2k=2n<⌊2n⌋+1
由于题干中给出了主要元素至少出现⌊n2⌋+1\lfloor \frac{n}{2} \rfloor + 1⌊2n⌋+1次的这个前提,而在假设最后一部分的candiate不是主要元素的条件下,我们导出了主要元素出现的最大次数为n+k2−⌈k/2⌉\frac{n+k}{2}- \lceil k/2 \rceil2n+k−⌈k/2⌉小于题干给出的最小出现次数,矛盾。 - 因此假设不成立,最终得到的candiate就是题干中所述的主要元素。