剑指 Offer 39. 数组中出现次数超过一半的数字
一、题目详情
原题链接:剑指 Offer 39. 数组中出现次数超过一半的数字
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入: [1, 2, 3, 2, 2, 2, 5, 4, 2]
输出: 2
限制:
- 1 <= 数组长度 <= 50000
二、哈希表法
class Solution {
public int majorityElement(int[] nums) {
Map<Integer,Integer> map = new HashMap<>();
//遍历 nums ,根据将 num 及其出现的频率通过 key-value 保存在 map 中
for(int num : nums){
if(map.containsKey(num)){
map.put(num,map.get(num) + 1);
}else{
map.put(num,1);
}
}
//定义多数元素
int max = Integer.MIN_VALUE;
for(Map.Entry<Integer, Integer> entry : map.entrySet()){
//如果出现频率大于一半,则赋值并跳出循环
if(entry.getValue() > nums.length / 2){
max = entry.getKey();
break;
}
}
return max;
}
}
三、排序法
当数组中存在 多数元素 时,对数组进行排序,排序后的数组的中点元素一定是 多数元素 。
class Solution {
public int majorityElement(int[] nums) {
Arrays.sort(nums);
return nums[nums.length / 2];
}
}
四、摩尔投票法
摩尔投票法 的核心理念为 票数正负抵消 。此方法时间和空间复杂度分别为 O(N) 和 O(1),为本题的最佳解法。
class Solution {
public int majorityElement(int[] nums) {
//初始化票数统计 vote = 0 , 众数 mode
int mode = 0, vote = 0;
for(int num : nums){
//当票数 votes 等于 0 ,则假设当前数字 num 是众数
if(vote == 0){
mode = num;
}
//当 num = mode 时,票数 vote 自增 1 ;当 num != mode 时,票数 vote 自减 1
vote += (mode == num) ? 1 : -1;
}
return mode;
}
}