给定一个长度为 n
的数组:java
int[] nums
其中有一个数,它出现的次数大于n/2
,称为主要元素,找到它。python
看起来不算是个难题,但好玩。算法
这是一个投票问题,能够模拟咱们在投票表决时的计票过程。用一个hash table或者dictionary,数组中的数做为key,它们出现的次数为value。本文想讨论的是下边这些算法。数组
结论很简单:排序完以后,主要元素必然在下标n/2
的位置。看下面两个例子就很清楚了:code
nums: 1, 1, 1, 2, 2 i 0 1 2 3 4 n/2 =5/2 =2 nums[2]=1 主要元素是最小的数,排序后集中在最左边
nums: 1, 1, 2, 2, 2 i 0 1 2 3 4 n/2 =5/2 =2 nums[2]=2 主要元素是最大的数,排序后集中在最右边
若是主要元素既不是最大的也不是最小的,那主要元素集中在中间一段,包括n/2
。Python一句搞定:排序
def majorityElement(self, nums): return sorted(nums)[len(nums)/2]
分析:元素是int型,没有限制更小的范围,基于比较的排序算法,最快O(nlogn)。get
这里设int为32位整数。咱们对这些数以二进制的形式,逐位观察,尝试构造出主要元素来。对32位中的每一位,若是1占多数,则主要元素的对应位为1,不然为0。hash
nums: 1, 2, 3, 3, 3 Binary: 1: 0b0000....0001 2: 0b0000....0010 3: 0b0000....0011 3: 0b0000....0011 3: 0b0000....0011 major: 0b0000....0011
Java实现:it
public int majorityElement(int[] nums) { int res=0,major=nums.length/2; for (int i=31;i>=0;i--){ int pos=0; for(int n:nums) pos+=(n>>i)&1; pos=pos>major? 1:0; res|=pos<<i; } return res; }
分析:时间复杂度为O(n),带个系数32,实际工做起来仍是很快的。io
提出Boyer-Moore 算法的论文。
基本思想:
比较直观的解释:在数组中找到两个不相同的元素并删除它们,不断重复此过程,直到数组中元素都相同,那么剩下的元素就是主要元素。
思想并不复杂,可是要凭空想出这个算法来也不是件容易的事。另外,给咱们的是数组,直接在里面删除元素是很费时的。取而代之,能够利用一个计数变量来实现。
def majorityElement(self, nums): count,major=0,0 for n in nums: if count==0: major=n if major==n: count+=1 else: count-=1 return major
对于上面的代码:
先随意肯定一个候选元素,count是候选元素的计数,当遇到一个跟候选元素不一样的元素时,二者数量上抵消一个,count减1。一旦count变成0,就从新找一个候选元素。
当遇到一个与候选元素不一样的元素时,就要抵消。对于候选元素和当前元素,可能存在两种状况:
A. 二者中有一个正好是主要元素
B. 二者都不是主要元素
对于状况 A,抵消事后,主要元素仍是主要元素;对于状况 B,能够说主要的元素的地位获得了巩固。因此算法最终能找到主要元素。