剑指Offer-数组中出现次数超过一半的数字
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入: [1, 2, 3, 2, 2, 2, 5, 4, 2]
输出: 2
思路一
HashMap解决。遇到统计次数的题目,往map想。统计数组中元素频率超过数组一半的元素即可。
class Solution {
public int majorityElement(int[] nums) {
int n=nums.length;
//数组元素值->出现次数
Map<Integer,Integer> map=new HashMap<>();
for(int i=0;i<nums.length;i++)
{
int key=nums[i];
if(map.get(key)==null)
{
map.put(key,0);
}else
{
int value=map.get(key);
value+=1;
map.put(key,value);
}
}
for(Integer key:map.keySet())
{
if(map.get(key)>=(n/2))
{
return key;
}
}
return 0;
}
}
思路二
排序,排序完成之后出现超过一半的数一定位于数组的中点。时间复杂度NlogN。
思路三
摩尔投票法。如果一个数字出现次数大于数组长度的一半,则它的出现次数大于其他元素出现次数的总和。
我们可以用一个计数器加1减1,当计数器为0时,就是对某个元素重新计数,最终计数器的值一定大于0,而所记录的对应的元素就是我们要找的元素。
class Solution {
public int majorityElement(int[] nums) {
int res=0;//记录结果
int votes=0;//计数器
for(int num:nums)
{
//计数器为0,则重新给这个元素计数
if(votes==0) res=num;
//如果当前元素与res相等,则计数器加1,否则减1,最终计数器的值必然大于0
votes+=(num==res?1:-1);
}
return res;
}
}