给定一个大小为 n_ _的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
**输入:nums = [3,2,3] **
输出:3
示例 2:
**输入:nums = [2,2,1,1,1,2,2] **
输出:2
提示:
- n == nums.length
- 1 <= n <= 5 * 104
- -109 <= nums[i] <= 109
**进阶:**尝试设计时间复杂度为 O(n)、空间复杂度为 O(1) 的算法解决此问题。
最简单的暴力方法是,枚举数组中的每个元素,再遍历一遍数组统计其出现次数。该方法的时间复杂度是 O(n2),会超出时间限制,因此我们需要找出时间复杂度小于 O(n2) 的优秀做法。
解题
hash法
思路:
因为出现次数最多的元素 大于n/2次,所以可以用哈希表来快速统计每个元素出现的次数。
算法:
我们使用哈希映射(HashMap)来存储每个元素以及出现的次数。对于哈希映射中的每个键值对,键表示一个元素,值表示该元素出现的次数。
我们用一个循环遍历数组 nums 并将数组中的每个元素加入哈希映射中。在这之后,我们遍历哈希映射中的所有键值对,返回值最大的键。我们同样也可以在遍历数组 nums 时候使用打擂台的方法,维护最大的值,这样省去了最后对哈希映射的遍历。
力扣官方题解
链接:https://leetcode.cn/problems/majority-element/solutions/146074/duo-shu-yuan-su-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
public int majorityElement02(int[] nums) {
Map<Integer, Integer> counts = new HashMap<>();
for (int num : nums) {
if (!counts.containsKey(num)) {
counts.put(num, 1);//初始化num:counts
} else {
counts.put(num, counts.get(num) + 1);
}
}
return getNum(counts);
}
private int getNum(Map<Integer, Integer> counts) {
Map.Entry<Integer, Integer> majorityEntry = null;
for (Map.Entry<Integer, Integer> entry : counts.entrySet()) {
if (majorityEntry == null || entry.getValue() > majorityEntry.getValue()) {
majorityEntry = entry;
}
}
return majorityEntry.getKey();
}
打擂:
public int majorityElement03(int[] nums) {
Map<Integer, Integer> counts = new HashMap<>();
int key = 0, v = 0;
for (int num : nums) {
if (!counts.containsKey(num)) {
counts.put(num, 1);//初始化num:counts
} else {
counts.put(num, counts.get(num) + 1);
}
if (v < counts.get(num)) {
v = counts.get(num);
key = num;
}
}
return key;
}
排序
如果数组nums 中的所有元素有序,那么下标为n/2的元素一定是众数。
mid = l + ((r-l)>>1);
那么无论nums.length是奇数还是偶数,nums[mid]一定为众数。
public int majorityElement01(int[] nums) {
//因为元素需要计算元素出现次数,那么排序后的数组元素nums[mid] 必然指向所求元素;
Arrays.sort(nums);
return nums[nums.length / 2];
}