169. Majority Element
题目地址
这道题目实际上是一道求众数的问题,题目的关键more than ⌊ n/2 ⌋
主要有三种思路
- 方法一:排序后取
nums[n/2]
,时间复杂度O(nlogn)
(这里使用了快排)
由于所求数的个数一定大于[n/2]
,所以排序后[n/2]
的位置一定是众数
int majorityElement(vector<int>& nums) {
int count=1;
int n=nums.size();
sort(nums.begin(),nums.end());
return nums[n/2];
}
- 方法二:位操作 时间复杂度
O(n)
这是之后看到大神做的一种方法(https://www.jianshu.com/p/dfd676b71ef0)在这里贴出思路和代码
设int为32位整数。我们对这些数以二进制的形式,逐位观察,尝试构造出主要元素来。对32位中的每一位,如果1占多数,则主要元素的对应位为1,否则为0
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)
这个算法算是本题最大的收获了~很有趣的一个算法 维基百科:Moore majority vote algorithm
基本思想就是找到两个不相同的元素然后删除,直到最后剩下的元素都相同,在数组中我们可以通过设置计数变量
来实现。摩尔算法的缺点
是找到的元素不一定是多数元素 需要后续验证
int majorityElement(int[] num) {
int major=num[0], count = 1;
for(int i=1; i<num.length;i++){
if(count==0){
count++;
major=num[i];
}else if(major==num[i]){
count++;
}else count--;
}
return major;
}
之后又趁热打铁做了 229. Majority Element II 题目链接
条件改为 find all elements that appear more than ⌊ n/3 ⌋ times
将摩尔多数票算法进行拓展,就可以解决该问题。根据题意,候选元素的个数只可能是 0个,1个,2个
我们可以设置两组计算变量和候选元素变量 count1,major1
,count2,major2
。注意:最后需要对候选元素进行验证
vector<int> majorityElement(vector<int>& nums) {
vector<int> res;
int n=nums.size();
int count1=0,count2=0;
int k1=0,k2=0;
if(n==0)
{
return res;
}
if(n==1)
{
return nums;
}
int major1=nums[0],major2=nums[1];
for(int i=0;i<n;i++)
{
if(major1==nums[i])
{
count1++;
}
else if(major2==nums[i])
{
count2++;
}
else if(count1==0)
{
major1=nums[i];
count1=1;
}
else if(count2==0)
{
major2=nums[i];
count2=1;
}
else
{
count1--;
count2--;
}
}
for(int j=0;j<n;j++)
{
if(major1==nums[j])
{
k1++;
}
if(major2==nums[j])
{
k2++;
}
}
if(k1>n/3)
res.push_back(major1);
if(k2>n/3&&major1!=major2)
res.push_back(major2);
return res;
}