题目描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
三种方案:
1.最简单,复杂度最高,而且使用stl。用map库映射。
class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers) {
map<int, int> Q;
int max = 0, res = 0;
for(int i = 0; i < numbers.size();i++){
if(Q.find(numbers[i]) == Q.end() ){
Q[numbers[i]] = 1;
}
else Q[numbers[i]]++;
if(Q[numbers[i]] > max){
max = Q[numbers[i]];
res = numbers[i];
}
}
if(max>numbers.size()/2)
return res;
return 0;
}
};
2.因为有一个数字出现次数超过数组长度一半,所以按照大小排序后,如果存在满足要求的数字,那么一定是中间那一个,接着验证就可以了。(nlogn)
class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers)
{
// 因为用到了sort,时间复杂度O(NlogN),并非最优
if(numbers.empty()) return 0;
sort(numbers.begin(),numbers.end()); // 排序,取数组中间那个数
int middle = numbers[numbers.size()/2];
int count=0; // 出现次数
for(int i=0;i<numbers.size();++i)
{
if(numbers[i]==middle) ++count;
}
return (count>numbers.size()/2) ? middle : 0;
}
};
3.定义两个int变量,一个保存遍历到的数n,一个保存次数count。后遍历到的数与前一个相同,则count+1,若不同,则count--.若count为0,则替换成后遍历到的数。遍历完保存的即为可能要返回的数。最后做一次验证。 O(n)
class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers)
{
if(numbers.empty()) return 0;
// 遍历每个元素,并记录次数;若与前一个元素相同,则次数加1,否则次数减1
int result = numbers[0];
int times = 1; // 次数
for(int i=1;i<numbers.size();++i)
{
if(times == 0)
{
// 更新result的值为当前元素,并置次数为1
result = numbers[i];
times = 1;
}
else if(numbers[i] == result)
{
++times; // 相同则加1
}
else
{
--times; // 不同则减1
}
}
// 判断result是否符合条件,即出现次数大于数组长度的一半
times = 0;
for(int i=0;i<numbers.size();++i)
{
if(numbers[i] == result) ++times;
}
return (times > numbers.size()/2) ? result : 0;
}
};