题目如下
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入: [1, 2, 3, 2, 2, 2, 5, 4, 2]
输出: 2
自己的算法及代码
- 看到这个题目,首先想到的是用 Map 去处理。因为,要获取到数组的每个元素,以及他们的出现次数,且 Map 的键不能重复。所以,选择用 HashMap 来进行存储,key 用来放数组中的元素,value 用来放元素出现的次数。
- 算法过程如下:
-
创建 HashMap 集合;
-
遍历数组,将数组的元素添加到 map 的 key 中;
(map.containsKey(nums[i])
为 true 表示key中已经有该元素)- 如果 key 中没有 元素nums[i] ,则将 key=nums[i],value=1 添加到 map 中;
- 如果 key 中已经有 元素nums[i],则将 key=nums[i] 时的 value 值取出,进行value++ 操作后,更新 value 值;
-
执行完上面的循环后,数据已经全部处理完毕,下来进行读取;
-
遍历 map 中的 key,如果 key 对应的 value 值,满足
value > nums.length/2
,则返回 key ;
-
public class Solution {
public static int majorityElement(int[] nums) {
int result = 0;
int count = 0;
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int i = 0; i < nums.length; i++){
if (!map.containsKey(nums[i])){
map.put(nums[i], 1);
}else {
count = (int) map.get(nums[i]);
count++;
map.put(nums[i], count);
}
}
for (Integer key : map.keySet()){
if (map.get(key) > nums.length/2){
result = key;
}
}
return result;
}
public static void main(String[] args) {
int[] nums = {1,2,3,2,2,2,5,4,2};
int result = majorityElement(nums);
System.out.println(result);
}
}
参考的算法及代码(投票法)
- 自己的算法虽然也是正确的,但时间和空间复杂度为 O(N);这个参考的代码,时间复杂度为 O(N),空间复杂度为 O(1),这里用到的是 摩尔投票法。
- 算法过程如下:
- 初始化: 票数统计 votes = 0 , 众数 x;
- 循环: 遍历数组 nums 中的每个数字 num ;
- 当 票数 votes = 0 ,则假设当前数字 num 是众数;
- 当 num = x 时,票数 votes 自增 1 ;当 num != x 时,票数 votes 自减 1 ;
- 返回值: 返回 x 即可;
class Solution {
public int majorityElement(int[] nums) {
int x = 0, votes = 0;
for(int num : nums){
if(votes == 0) x = num;
votes += num == x ? 1 : -1;
}
return x;
}
}
注:
votes += num == x ? 1 : -1;
等价于下面的语句:
if (num == x){
votes++;
} else {
votes--;
}