题目描述:
解法1:
这种解法是通过map集合去实现,定义一个map集合,key是数组元素,value是数组元素出现的次数。我们遍历数组元素,当map集合中有相同数组元素的时候,就把它的出现次数加1,没有出现过,则把数组元素和出现次数1放进去。当有元素出现的次数大于数组长度的一半时,就返回此元素。
class Solution {
public int majorityElement(int[] nums) {
int length=(int)Math.ceil(nums.length/2.0);
Map<Integer,Integer> map=new HashMap<>();
for(int num:nums){
if(map.containsKey(num)){
map.put(num,map.get(num)+1);
}
else{
map.put(num,1);
}
if(map.get(num)>=length) return num;
}
return -1;
}
}
解法2:
这种解法是通过排序去实现的,速度上比上面通过map集合实现要快很多。我们首先将数组从小到大排序,因为数组中存在一个出现次数大于数组长度一半的元素,所以排序后数组中间的元素,一定是出现次数大于一半长度的元素,直接返回它即可。
class Solution {
public int majorityElement(int[] nums) {
int size=(int)Math.ceil(nums.length/2);
System.out.println(size);
Arrays.sort(nums);
return nums[size];
}
}
解法3:
这种解法使用的是摩尔投票法,运行时间和占用内存都接近击败100%。这种解法的原理就是,因为数组中存在一个多次出现的元素,且这个元素出现的次数超过数组长度的一半,其实这个数相当于众数,其他的元素就是非众数。我们可以遍历数组元素,当数组元素和后一位的元素不相同时,就相互抵消,用votes表示投票数,当相同时,票数加1。最后返回票数最多的那个元素,验证它的出现次数是否大于数组长度的一半,是则直接返回此元素。
class Solution {
public int majorityElement(int[] nums) {
int x = 0, votes = 0, count = 0;
for(int num : nums){
if(votes == 0) x = num;
votes += num == x ? 1 : -1;
}
// 验证 x 是否为众数
for(int num : nums)
if(num == x) count++;
return count > nums.length / 2 ? x : 0; // 当无众数时返回 0
}
}