题目描述:
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入: [1, 2, 3, 2, 2, 2, 5, 4, 2]
输出: 2
限制:
1 <= 数组长度 <= 50000
代码:
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* @author :xxx
* @description:TODO
* @date :2021/10/19 17:18
*/
public class jianzhi39 {
/*
哈希,将数组中出现的数及其出现的次数存到map中,这样我们就只需要找对应的map中最大的value所对应的key即可。
时间复杂度:O(nums.length)
空间复杂度:O(nums.length)
*/
public int majorityElement(int[] nums) {
Map<Integer,Integer> map = new HashMap<>();
for (int num : nums){
if (!map.containsKey(num)){
map.put(num,1);
}
else {
map.put(num,map.get(num)+1);
}
}
int ansk = -1,ansv = -1;
for (Map.Entry<Integer,Integer> entry : map.entrySet()){
if (entry.getValue() > ansv){
ansk = entry.getKey();
ansv = entry.getValue();
}
}
return ansk;
}
/*
排序
时间复杂度O(NlogN)
空间复杂度O(logN)
*/
public int majorityElement1(int[] nums) {
Arrays.sort(nums);
return nums[nums.length/2];
}
/*
摩尔选举法:该问题其实就是有一群候选人,其中一个候选人得票数大于总投票数的一半,让你找到这个候选人,所以可以使用摩尔选举。
我们将情况只分为两种:值为A,值不为A,cnt用来统计A的个数,cand就是A。
当num值为A时,我们将cnt+1,当值不为A的时候,我们将cnt-1,当cnt为0时,我们取下一个数,将其重新作为A。
这样当我们遍历完一边数组时,所得到的cand一定就是我们要寻找的众数。
时间复杂度:O(N)
空间复杂度:O(1)
*/
public int majorityElement2(int[] nums) {
int cnt = 0;
int cand = 0;
for (int num : nums){
if (cnt == 0){
cand = num;
}
cnt += (cand == num) ? 1 : -1;
}
return cand;
}
public static void main(String[] args) {
jianzhi39 obj = new jianzhi39();
System.out.println(obj.majorityElement2(new int[]{1, 2, 3, 2, 2, 2, 5, 4, 2}));
}
}