数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入: [1, 2, 3, 2, 2, 2, 5, 4, 2]
输出: 2
限制:
- 1 <= 数组长度 <= 50000
分析:
方法1:哈希表统计
利用哈希表统计每个数字出现的次数即可,当该数字大于长度一半时直接返回。
时间复杂度:O(n)
空间复杂度:O(n)
class Solution {
public int majorityElement(int[] nums) {
//存储哈希表记录每个元素的数量
HashMap<Integer, Integer> map = new HashMap<>();
//记录数组长度一半
int half = nums.length / 2;
//遍历数组
for(int n: nums){
//获取该数的数量,默认为0
int i = map.getOrDefault(n, 0);
//大于数组长度一半直接返回该数
if(++i > half){
return n;
}
map.put(n, i);
}
return -1;
}
}
方法2:摩尔投票法
因为这道题说了总有一个数一定大于数组长度的一半,那么我们可以进行投票,票数为 0 时选择当前对象为新的投票对象,和投票对象一样加1(包括自己),不一样减1,因为这个数的数量是大于总数量的一半的,所以无论如何,该数的票数一定大于0。比如 [1, 2, 3, 2, 2, 2, 5, 4, 2]:
- 1 选为投票对象,票数为 1
- 2 与 1 不一样,票数减1,为 0
- 票数为 0,3 选为新的投票对象,票数为 1
- 3 与 2 不一样,票数减1,为 0
- 票数为 0,2 选为新的投票对象,票数为 1
- 2 与 2 一样,票数加1,为 2
- 2 与 5 不一样,票数减1,为 1
- 2 与 4 不一样,票数减1,为 0
- 票数为 0,2 选为新的投票对象,票数为 1
- 遍历完成,返回 2
时间复杂度:O(n)
空间复杂度:O(1)
class Solution {
public int majorityElement(int[] nums) {
//定义投票对象和票数
int res = 0, vote = 0;
//遍历
for(int n: nums){
//票数为0 投票对象变为新的一个
if(vote == 0){
res = n;
vote = 1;
}
//该数与投票对象不一样,票数减一,否则加一
else if(res != n){
vote--;
}else{
vote++;
}
}
return res;
}
}
题目来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shu-zu-zhong-chu-xian-ci-shu-chao-guo-yi-ban-de-shu-zi-lcof