一、题目
- 169. 多数元素 - 力扣(LeetCode)
- 给定一个大小为
n
的数组nums
,返回其中的多数元素。多数元素是指在数组中出现次数 大于⌊ n/2 ⌋
的元素。- 你可以假设数组是非空的,并且给定的数组总是存在多数元素。
二、思路
- 根据题目对多数元素的定义,多数元素的数量肯定超过数组总元素的一半;
- 但是他的存在又是随机的、分散的,要怎么提炼出来呢,将数组排序后中间的值肯定就是要求的结果;
- 但是又想到了中位数的问题,如果数组是偶数怎么办,想了一会儿发现想多了,既然多数元素超过数组总元素的一半,那不管怎么取值都会取到这个多数元素,故有方法一;
- 写代码的时候觉得哈希表很适合解这个题,库库往里塞数据,哪个数据超过总元素一半了直接返回就完事儿了,故有方法二;
三、解法
解法一
class Solution {
public int majorityElement(int[] nums) {
Arrays.sort(nums);
return nums[nums.length / 2];
}
}
解法二
class Solution {
private HashMap<Integer, Integer> map = new HashMap<>();
public int majorityElement(int[] nums) {
int len = nums.length;
for (int i = 0; i < len; i++) {
int pre = map.getOrDefault(nums[i], 0) + 1;
if (pre > len / 2) {
return nums[i];
}
map.put(nums[i], pre);
}
return 0;
}
}
解法三
- 进阶:尝试设计时间复杂度为 O(n)、空间复杂度为 O(1) 的算法解决此问题。
class Solution {
public int majorityElement(int[] nums) {
int candidate = nums[0], count = 0;
for (int num : nums) {
if (count == 0) {
candidate = num;
}
count += (num == candidate) ? 1 : -1;
}
return candidate;
}
}
解析:遍历整个数组,同时维护两个变量,count 用于存放当前元素的数量,candidate 用于存放当前遍历到的元素,遇到相同元素时 count + 1,不同元素则 count - 1 ,每当这个变量被扣减为 0 时,下轮循环时将当前元素填入 candidate,可以想象每次遇到不同元素时 count 就会被"抵消"掉一个,而因为多数元素总是比其他所有元素总和多 1,所以"抵消"到最后必剩下一个元素,且该元素为多数元素。