题目描述
解题思路
哈希法
public int majorityElement(int[] nums) {Map<Integer, Integer> map = new HashMap<>();for (int i = 0; i < nums.length; i++) {map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);}for (Map.Entry<Integer, Integer> entry : map.entrySet()) {if (entry.getValue() > nums.length / 2) return entry.getKey();}return 0;}
排序法
由于一定有众数,且众数占数组长度一半,所以排序之后取中间值。
public int majorityElement(int[] nums) {Arrays.sort(nums);return nums[nums.length / 2];}
摩尔投票法
推论一: 若记 众数 的票数为 +1 ,非众数 的票数为 -1 ,则一定有所有数字的 票数和 > 0 。
推论二: 若数组的前 a 个数字的 票数和 =0 ,则 数组剩余 (n-a) 个数字的 票数和一定仍 >0 ,即后 (n-a) 个数字的 众数仍为 x 。
根据以上推论,记数组首个元素为n,众数为α,遍历并统计票数。
当发生票数和=0时,剩余数组的众数一定不变,这是由于:
- 当n1= a :抵消的所有数字,有一半是众数α。
 - 当n1≠a :抵消的所有数字,众数α的数量最少为0个,最多为一半。
 
利用此特性,每轮假设发生票数和=0都可以缩小剩余数组区间。当遍历完成时,最后一轮假设的数字即为众数。
也就是把第一个数字当作备选者,遍历数组,如果相同则选举加一,如果不相同则选举减一,当选举为0的时候,此时就需要重新选择备选者进行投票。
// 投票法public int majorityElement(int[] nums) {int x = 0, votes = 0;for (int num : nums) {if (votes == 0) x = num;if (num == x) votes++;else votes--;}// 如果不存在众数,需要遍历x进行验证本题说明了存在众数/*int count = 0;for (int num : nums) {if (x == num) count++;}if (count > nums.length / 2) return x;*/return x;}
扩展
此时如果大于数组长度一半的众数不一定存在,那么最后一个数就不一定是需要找的众数,所以还需要遍历一次数字,使用计数器技术到底该数是不是需要找的数。
// 投票法public int majorityElement(int[] nums) {int x = 0, votes = 0;for (int num : nums) {if (votes == 0) x = num;if (num == x) votes++;else votes--;}// 如果不存在众数,需要遍历x进行验证本题说明了存在众数int count = 0;for (int num : nums) {if (x == num) count++;}if (count > nums.length / 2) return x;return x;}
