原文链接: https://leetcode-cn.com/problems/find-majority-element-lcci
英文原文
A majority element is an element that makes up more than half of the items in an array. Given a integers array, find the majority element. If there is no majority element, return -1. Do this in O(N) time and O(1) space.
Example 1:
Input: [1,2,5,9,5,9,5,5,5] Output: 5
Example 2:
Input: [3,2] Output: -1
Example 3:
Input: [2,2,1,1,1,2,2] Output: 2
中文题目
数组中占比超过一半的元素称之为主要元素。给你一个 整数 数组,找出其中的主要元素。若没有,返回 -1
。请设计时间复杂度为 O(N)
、空间复杂度为 O(1)
的解决方案。
示例 1:
输入:[1,2,5,9,5,9,5,5,5] 输出:5
示例 2:
输入:[3,2] 输出:-1
示例 3:
输入:[2,2,1,1,1,2,2] 输出:2
通过代码
高赞题解
哈希表
一个朴素的做法是使用哈希表进行计数,如果发现某个元素数量超过总数一半,说明找到了答案。
代码(感谢 @Benhao 同学提供的其他语言代码):
class Solution {
public int majorityElement(int[] nums) {
int n = nums.length;
Map<Integer, Integer> map = new HashMap<>();
for (int x : nums) {
map.put(x, map.getOrDefault(x, 0) + 1);
if (map.get(x) > n / 2) return x;
}
return -1;
}
}
class Solution:
def majorityElement(self, nums: List[int]) -> int:
n = len(nums)
hashmap = defaultdict(int)
for x in nums:
hashmap[x] += 1
if hashmap[x] > n // 2:
return x
return -1
- 时间复杂度:$O(n)$
- 空间复杂度:$O(n)$
摩尔投票
这还是道「摩尔投票」模板题。
摩尔投票 :在集合中寻找可能存在的多数元素,这一元素在输入的序列重复出现并占到了序列元素的一半以上;在第一遍遍历之后应该再进行一个遍历以统计第一次算法遍历的结果出现次数,确定其是否为众数;如果一个序列中没有占到多数的元素,那么第一次的结果就可能是无效的随机元素。
换句话说,每次将两个不同的元素进行「抵消」,如果最后有元素剩余,则「可能」为元素个数大于总数一半的那个。
具体的,我们定义一个变量 $x$ 来保存那个可能为主要元素的值,$cnt$ 用来记录该值的出现次数。然后在遍历数组 $nums$ 过程中执行如下逻辑:
- 如果 $cnt$ 为 $0$:说明之前出现过的 $x$ 已经被抵消完了,更新一下 $x$ 为当前值,出现次数为 $1$:
x = nums[i], cnt = 1
; - 如果 $cnt$ 不为 $0$:说明之前统计的 $x$ 还没被抵消完,这是根据 $nums[i]$ 与 $x$ 是否相等进行计算即可:
cnt += nums[i] == x ? 1 : -1
。
当处理完 $nums$ 之后,我们得到了一个「可能」的主要元素。注意只是可能,因为我们在处理过程中只使用了 $x$ 和 $cnt$ 来记录,我们是无法确定最后剩下的 $x$ 是经过多次抵消后剩余的主要元素,还是只是不存在主要元素的数组中的无效随机元素。
因此我们需要再进行一次遍历,检查这个「可能」的主要元素 $x$ 的出现次数是否超过总数一半。
代码(感谢 @Benhao 同学提供的其他语言代码):
class Solution {
public int majorityElement(int[] nums) {
int n = nums.length;
int x = -1, cnt = 0;
for (int i : nums) {
if (cnt == 0) {
x = i;
cnt = 1;
} else {
cnt += x == i ? 1 : -1;
}
}
cnt = 0;
for (int i : nums) if (x == i) cnt++;
return cnt > n / 2 ? x : -1;
}
}
class Solution:
def majorityElement(self, nums: List[int]) -> int:
n = len(nums)
x, cnt = -1, 0
for i in nums:
if not cnt:
x = i
if x == i:
cnt += 1
else:
cnt -= 1
return x if cnt and nums.count(x) > n // 2 else -1
- 时间复杂度:$O(n)$
- 空间复杂度:$O(1)$
其他
在这个特别的小周五(2021/07/09),在 LeetCode 工作人员辛苦运作下,期待已久的 LeetBook 上线啦 💐💐
设计数据结构 : 本 LeetBook 将会和大家一起把面试题中常考察的数据结构实现一遍(由浅入深,从热门到常规)。
DP - 路径问题 : 一份「路径问题从入门到进阶」的究极指南。本 LeetBook 旨在通过「路径问题」来向大家分享通用的 DP 分析思路。
两本 LeetBook 都是「非会员 & 全免费」的哦,欢迎入手获取 ~
再次感谢 LeetCode 工作人员 尾鱼粥 和 笑笑同学 的辛苦付出 🍭🍭🍭
统计信息
通过次数 | 提交次数 | AC比率 |
---|---|---|
68186 | 119536 | 57.0% |
提交历史
提交时间 | 提交结果 | 执行时间 | 内存消耗 | 语言 |
---|