问题描述
给一个长度为 n 的数组,数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
例如输入一个长度为9的数组[1,2,3,2,2,2,5,4,2]。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
数据范围:n≤50000,数组中每个数的值:0≤val≤10000
要求:时间复杂度: O ( 1 ) O(1) O(1),空间复杂度: O ( n ) O(n) O(n)
示例
示例1
输入:[1,2,3,2,2,2,5,4,2]
返回值:2
示例2
输入:[3,3,3,3,2,2,2]
返回值:3
示例3
输入:[1]
返回值:1
具体思路
思路一
定义unordered_map,使用<数字,次数>的映射关系,最后统计每个字符出现的次数。
首先定义一个unordered_map<int,int>。然后计算出一半数组的大小,接着遍历整个数组,如果unordered_map中已经有该数就自增,否则就新插入,次数设为1。最后判断map中值出现最多次的是否大于整个数组长度的一半,是就返回数值,否则返回0。
思路二
排序,出现次数最多的数字,一定在中间位置。然后检测中间出现的数字出现的次数是否符合要求。
首先对整个数组进行排序,然后计算中间数组的值,接着遍历整个数组,对目标值进行次数的统计,最后判断目标值出现的次数是否大于数组长度的一半,是则返回数值,否则返回0.
思路三
目标条件:目标数据超过数组长度的一半,那么对数组,我们同时去掉两个不同的数字,到最后剩下的一个数就是该数字。(如果剩下两个,那么这两个也是一样的,就是结果),在其基础上把最后剩下的一个数字或者两个回到原来数组中,将数组遍历一遍统计一下数字出现次数进行最后判断。
首先需要考虑数组是否为空的情况,然后对数组从前往后进行抵消,如果相同,计数就+1,不同计数就-1,接着计算最后剩下的数字在整个数组中出现的次数,最后判断这个数出现的次数是否大于数组长度的一半,是就返回数值,否则返回0。
代码实现
思路一
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param numbers int整型vector
* @return int整型
*/
int MoreThanHalfNum_Solution(vector<int>& numbers) {
// write code here
int half=numbers.size()/2; //计算数组一半的长度
unordered_map<int,int> _map;
for(int i=0;i<numbers.size();i++)
{
auto it=_map.find(numbers[i]); //如果已经在unordered_map中,进行自增,如果不在,首次出现,插入
if(it==_map.end())
{
//_map.insert(make_pair(numbers[i],1)); //make_pair不需要指定模板类型,可以通过值生成pair对象
//_map.insert(pair<int,int>(numbers[i],1)); //pair可以将两个类型的数据封装到一个对象中
// _map.insert(pair(numbers[i],1));
//_map.insert({numbers[i],1});
}
else
{
_map[numbers[i]]++;
}
//自增或者插入一个,直接进行判定。注意,这里要考虑测试用例为{1}的情况
//走到这里,对应的key val一定存在
if(_map[numbers[i]]>half)
{
return numbers[i];
}
}
//走到这里,说明没有找到
return 0;
}
};
思路二
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param numbers int整型vector
* @return int整型
*/
int MoreThanHalfNum_Solution(vector<int>& numbers) {
// write code here
sort(numbers.begin(),numbers.end()); //默认为升序,即第三个参数为less<int>()
//sort(numbers.begin(),numbers.end(),greater<int>()); //如果想要降序则需要传greater<int>()
int target=numbers[numbers.size()/2]; //排序后出中间的数一定是出现次数最多的
int count=0;
for(int i=0;i<numbers.size();i++) //遍历整个数组,统计中间数的次数
{
if(target==numbers[i])
{
count++;
}
}
if(count>numbers.size()/2) //如果中间数的次数大于数组的一半就返回
{
return target;
}
return 0;
}
};
思路三
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param numbers int整型vector
* @return int整型
*/
int MoreThanHalfNum_Solution(vector<int>& numbers) {
// write code here
if(numbers.size()==0)
{
return 0;
}
//采用不用的数量进行抵消的思路
int number=numbers[0];
int times=1;
for(int i=1;i<numbers.size();i++)
{
if(times==0) //如果当前times是0,说明之前的不同数已经抵消完了
{
number=numbers[i];
times=1;
}
else if(number==numbers[i])
{
times++;
}
else
{
times--;
}
}
//如果输入本身满足条件,则times一定>0,并且number保存的就是准目标,但是还需要确认一下
int count=0;
for(int i=0;i<numbers.size();i++) //遍历数组统计出现的次数
{
if(number==numbers[i])
{
count++;
}
}
if(count>numbers.size()/2) //如果中间数的次数大于数组的一半就返回
{
return number;
}
else
{
return 0;
}
}
};