题目描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入: [1, 2, 3, 2, 2, 2, 5, 4, 2]
输出: 2
限制:
1 <= 数组长度 <= 50000
方法一(排序)
1.解题思路
先排序,然后取最中间的元素,一定是出现次数最多的。
2.代码实现
class Solution {
public int majorityElement(int[] nums) {
int n=nums.length;
Arrays.sort(nums);
return nums[n/2];
}
}
3.复杂度分析
- 时间复杂度:调用了排序接口,所以时间复杂度为O(n*logn)
- 空间复杂度:不需要额外的内存空间,所以空间复杂度为O(1)
方法二(哈希表)
1.解题思路
用哈希表记录每一个元素出现的次数,如果大于一半,则是出现次数最多的。
2.代码实现
class Solution {
public int majorityElement(int[] nums) {
int n=nums.length;
HashMap<Integer,Integer> map=new HashMap<>();
for(int num:nums){
map.put(num,map.getOrDefault(num,0)+1);
}
for(int num:nums){
if(map.get(num)>n/2){
return num;
}
}
return -1;
}
}
3.复杂度分析
- 时间复杂度:遍历了两次数组,所以时间复杂度为O(n)
- 空间复杂度:需要额外的哈希表来存储元素出现次数,所以空间复杂度为O(n)
方法三(摩尔投票法)
1.解题思路
把场景想象成一次阵地攻守战,最开始出现的那位是我方战士,如果下次出现的元素与我方战士的值不同,则表示出现的是敌人,我军阵营人数(count)减1,如果出现的值相同,则我军阵营人数加1;如果我军阵营人数为0,则重新确定新的战士。坚守到最后的战士则是出现次数超过一半的那个元素。
2.代码实现
class Solution {
public int majorityElement(int[] nums) {
int n=nums.length;
int num=nums[0];
int count=1;
for(int i=1;i<n;i++){
if(count==0){
num=nums[i];
}
if(nums[i]==num){
count++;
}
else{
count--;
}
}
return num;
}
}
3.复杂度分析
- 时间复杂度:只需遍历一次数组,所以时间复杂度为O(n)
- 空间复杂度:需要额外常数级别的内存空间,所以空间复杂度为O(1)
剑指offer全集入口: 请戳这里