给定一个整型数组,找到主元素,它在数组中的出现次数严格大于数组元素个数的三分之一。
样例
给出数组[1,2,1,2,1,3,3] 返回 1
挑战
要求时间复杂度为O(n),空间复杂度为O(1)。
注意事项
数组中只有唯一的主元素
解题思路1:
一开始就想到使用哈希表存储,然后查找即可,时间复杂度为O(n),空间复杂度为O(n)。
class Solution {
public:
/*
* @param nums: a list of integers
* @return: The majority number that occurs more than 1/3
*/
int majorityNumber(vector<int> &nums)
{
// write your code here
unordered_map<int , int> m;
int length = nums.size();
for(int num : nums)
{
m[num]++;
if(m[num] > (length/3))
return num;
}
}
};
解题思路2:
这道题让我们求出现次数大于n/3的众数,而且限定了时间和空间复杂度,那么就不能排序,也不能使用哈希表,这么苛刻的限制条件只有一种方法能解了,那就是摩尔投票法 Moore Voting,这种方法在之前那道题Lintcode 46:Majority Number中也使用了。这里有个重要的结论:任意一个数组出现次数大于n/3的众数最多有两个,具体的证明我就不会了,我也不是数学专业的。那么有了这个信息,我们使用投票法的核心是找出两个候选众数进行投票,需要两遍遍历,第一遍历找出两个候选众数,第二遍遍历重新投票验证这两个候选众数是否为众数即可,选候选众数方法和前面那篇一样。
注意第一个循环中的顺序不能轻易修改,注意理解两个众数的顺序,代码如下:
class Solution {
public:
/*
* @param nums: a list of integers
* @return: The majority number that occurs more than 1/3
*/
int majorityNumber(vector<int> &nums)
{
// write your code here
int res1 = 0 , count1 = 0;
int res2 = 0 , count2 = 0;
for(int num : nums)
{
if(count1 == 0)
{
res1 = num;
count1++;
}
else if(res1 == num)
count1++;
else if(count2 == 0)
{
res2 = num;
count2++;
}
else if(res2 == num)
count2++;
else
{
count1--;
count2--;
}
}
count1 = 0;
count2 = 0;
for(int num : nums)
{
if(num == res1)
count1++;
else if(num == res2)
count2++;
}
if(count1 > nums.size()/3)
return res1;
else
return res2;
}
};