题目
方法一-哈希表统计法
算法思路
该方法最容易想到,即用一个哈希表来统计数组中各个数字出现的次数,超过数组长度一半的就是“众数”。
对于哈希映射中的每个键值对,key表示一个元素,value表示该元素出现的次数。
具体代码
class Solution {
public int majorityElement(int[] nums) {
Map<Integer, Integer> map = new HashMap<>();
int n = nums.length / 2;
for(int num : nums){
map.put(num, map.getOrDefault(num, 0) + 1);//更新出现次数
if(map.get(num) > n)return num;//找到众数
}
return 0;
}
}
复杂度分析
- 时间复杂度: O ( n ) O(n) O(n),n 为数组长度
- 空间复杂度: O ( n ) O(n) O(n),用到了额外空间,哈希表最多包含 n − ⌊ n / 2 ⌋ n−⌊n/2⌋ n−⌊n/2⌋个键值对,所以占用的空间为 O ( n ) O(n) O(n)
方法二-排序
算法思路
将数组中元素递增或递减排序,排序后下标为 ⌊ n / 2 ⌋ ⌊n/2⌋ ⌊n/2⌋ 的元素一定就是众数
具体代码
class Solution {
public int majorityElement(int[] nums) {
Arrays.sort(nums);//排序
return nums[nums.length / 2];
}
}
复杂度分析
- 时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn),n 为数组长度,由于题设中 n 最大可以达到5000,这里按归并排序考虑
- 空间复杂度: O ( l o g n ) O(logn) O(logn),排序算法用到的栈空间(?)
方法三-投票
算法思路
Boyer-Moore 投票算法,两两抵消,要么众数抵消掉非众数,要么非众数抵消掉非众数,最后剩下来的一定是众数。
算法流程:
- 初始化:候选众数
candidate = nums[0]
,计数值cnt = 0
- 遍历数组,设当前元素为
num
1.若num == candidate
,则计数值加1
2.若num != candidate
,则计数值减1,当计数值cnt == 0
时,更换众数为当前元素,即执行candidate = num
- 返回值:
candidate
具体代码
class Solution {
public int majorityElement(int[] nums) {
int candidate = nums[0];//候选众数初始化
int cnt = 0;//计数值初始化
for(int num : nums){
if(num == candidate)cnt++;
else{
cnt--;
if(cnt == 0){
candidate = num;
cnt++;
}
}
}
return candidate;
}
}
复杂度分析
- 时间复杂度: O ( n ) O(n) O(n),n 为数组长度
- 空间复杂度: O ( 1 ) O(1) O(1),只需要常数级别的额外空间