46. 主元素
给定一个整型数组,找出主元素,它在数组中的出现次数严格大于数组元素个数的二分之一。
样例
给出数组[1,1,1,1,2,2,2],返回 1
1、用哈希表,存储数组中每个元素出现的次数,然后判断其是否大于数组元素个数的二分之一,时间复杂度O(n)。
2、随机算法,每次随机产生一个位置,对这个位置的数进行计数,看是不是主元素,时间复杂度O(n^2)。
3、此题还可以用找中位数法,见查找中位数方法点击打开链接
1、哈希表
class Solution {
public:
/*
* @param nums: a list of integers
* @return: find a majority number
*/
int majorityNumber(vector<int> &nums) {
// write your code here
//用哈希表
int n=nums.size();
unordered_map<int,int>result;
for(int i=0;i<n;i++)
{
if(++result[nums[i]]>n/2)
return nums[i];
}
return -1;
}
};
2、随机化算法
class Solution {
public:
/*
* @param nums: a list of integers
* @return: find a majority number
*/
int majorityNumber(vector<int> &nums) {
// write your code here
//用随机算法
int n=nums.size();
srand(unsigned(time(0)));
int count=0;
while(true)
{ int indx=rand()%n;
int candiate=nums[indx];//在每个for循环内candiate是确定的。最多只需要n/2次就可以找到
for(int i=0;i<n;i++)
if(candiate==nums[i])
count++;
if(count>n/2)
return candiate;
}
}
};
3、枚举算法 (经典算法)
思想:先假设第一个数是主元素,若第二个数与其相同,则count+1,否则count-1。判断count的值,当count减到零时,说明第一个可能不是主元素(如1 1 2 2 1),因为目前两个元素数量相同,就将当下一个值赋给candiate,继续判定,最后的candiate就是主元素。如果不等于零,那么继续判断
现在举例介绍思路如下:
例1:
2,3,1,1,2,1,1
- 1
第一个元素和第二个元素均不是主元素,那么count的变化,就是count=1然后count-1,结果是count=0,需要从第三个元素重新开始,重复上述操作。而这一变化对应的是从数组中消除了两个非主元素。
例2:
1,1,2,3,1,1,2
- 1
同样的如果是主元素和非主元素相抵消,如1,1,2,3
相抵消,对最终结果也没什么影响,到了3
后的1
自然还是重新设置count=1,相当于对1,1,2
进行主元素查找。
class Solution {
public:
/*
* @param nums: a list of integers
* @return: find a majority number
*/
int majorityNumber(vector<int> &nums) {
// write your code here
int candidate, count = 0;
for (int i = 0; i < nums.size(); i++)
{
if (count == 0)
{
candidate = nums[i];
count ++;
}
else
{
if (candidate == nums[i])
{
count ++;
}
else
{
count --;
}
}
}
return candidate;
}
};
47. 主元素 II
给定一个整型数组,找到主元素,它在数组中的出现次数严格大于数组元素个数的三分之一。
注意事项
数组中只有唯一的主元素
给出数组[1,2,1,2,1,3,3] 返回 1
枚举算法(经典算法)比较复杂,又容易出错
class Solution {
public:
int majorityNumber(vector<int> nums) {
int candidate1, candidate2;
int count1, count2;
count1 = count2 = 0;
for (int i = 0; i < nums.size(); i++) {
if (candidate1 == nums[i]) {
count1 ++;
} else if (candidate2 == nums[i]) {
count2 ++;
} else if (count1 == 0) {
candidate1 = nums[i];
count1 = 1;
} else if (count2 == 0) {
candidate2 = nums[i];
count2 = 1;
} else {
count1--;
count2--;
}
}
count1 = count2 = 0;
for (int i = 0; i < nums.size(); i++) {
if (nums[i] == candidate1) {
count1++;
} else if (nums[i] == candidate2) {
count2++;
}
}
return count1 > count2 ? candidate1 : candidate2;
}
};
下面我们尝试用快速排序法做
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
Qsort(nums,0,nums.size()-1);
int count=1;
for(int i=0;i<nums.size()-1;i++)
{
if(nums[i]==nums[i+1])
{
count++;
if(count>nums.size()/3)
return nums[i];
}
else count=1;
}
}
void Qsort(vector<int> &nums,int low,int high)
{
int pivot;
if(low<high)
{
pivot=parition(nums,low,high);
Qsort(nums,low,pivot-1);
Qsort(nums,pivot+1,high);
}
}
int parition(vector<int> &nums,int low,int high)
{
int pivotkey,temp;
pivotkey=nums[low];
while(low<high)
{
while(low<high&&nums[high]>=pivotkey)
high--;
temp=nums[high];
nums[high]=nums[low];
nums[low]=temp;
while(low<high&&nums[low]<=pivotkey)
low++;
temp=nums[high];
nums[high]=nums[low];
nums[low]=temp;
}
return low;
}
};