题目地址:
今天刷多数元素,大家有兴趣可以点上看看题目要求,试着做一下。
我们直接看题解吧:
这里有五种解题方法,不过我主要看哈希表法和摩尔投票法,剩下几个也挺有意思的,大家有兴趣话也可以看看的。
- 哈希表
这个比较简单,应该大多数人首先想到的。
思路:设数组元素为x,遍历数组,放入哈希表,作为key,然后如果在哈希表中找到相同的value +1()统计出现次数,否则赋值1
代码:(力扣官方那个感觉有点不太了解,繁杂,下面的是我自己写的,时间和空间都比官方的好一点)
class Solution {
public int majorityElement(int[] nums) {
int n=nums.length;
HashMap <Integer,Integer> hashtable=new HashMap<Integer,Integer>();
for(int num:nums){
if(hashtable.containsKey(num)){
hashtable.put(num,hashtable.get(num)+1);
}
else{
hashtable.put(num,1);
}
}
for(int j=0;j<n;j++){
if(hashtable.get(nums[j])>n/2)
return nums[j];
}
return nums[-1];
}
}
- 摩尔投票法
这个在时间空间都是最佳的。
用这个方法关键要注意“多数元素”这个词
那么什么是多数元素?
多数元素表示在一个数组中出现次数最多,并且出现次数 > 数组总长度的一半的元素
因此,为何这算法行得通? 投票法是遇到相同的则 票数 + 1,遇到不同的则 票数 - 1。 且“多数元素”的个数 > ⌊ n/2 ⌋,其余元素的个数总和 <= ⌊ n/2 ⌋。 因此“多数元素”的个数 - 其余元素的个数总和 的结果 肯定 >= 1。 这就相当于每个 “多数元素” 和其他元素 两两相互抵消,抵消到最后肯定还剩余 至少1个 “多数元素”
实际上,这个算法核心就是“对拼消耗”
思路:
设数组元素为x,数组nums中的众数为m,数组元素出现次数为count,
如果 x 与 m 相等,那么计数器 count 的值增加 1;
如果 x 与 m 不等,那么计数器 count 的值减少 1。
当票数 count 为 0 时,更换候选人,并将票数 count 重置为 1
代码:
class Solution {
public int majorityElement(int[] nums) {
int cand_num = nums[0], count = 1;
for (int i = 1; i < nums.length; ++i) {
if (cand_num == nums[i])
++count;
else if (--count == 0) {
cand_num = nums[i];
count = 1;
}
}
return cand_num;
}
}
另外,关于这个算法的一些相关知识:
推论一: 若记 众数 的票数为 +1 ,非众数的票数为 −1 ,则一定有所有数字的票数和 >0 。
推论二: 若数组的前 a 个数字的 票数和 =0 ,则数组剩余 (n−a) 个数字的票数和一定仍 >0 ,即后 (n−a)个数字的众数仍为 x 。