Article / 文章
LeetCode 第169题:多数元素
给定一个大小为 n 的数组 nums,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。 你可以假设数组是非空的,并且给定的数组总是存在多数元素。
题目描述
给定一个大小为 n 的数组 nums,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
难度
简单
题目链接
示例
示例 1:
输入:nums = [3,2,3]
输出:3
示例 2:
输入:nums = [2,2,1,1,1,2,2]
输出:2
提示
n == nums.length1 <= n <= 5 * 10^4-10^9 <= nums[i] <= 10^9
解题思路
方法一:哈希表计数
使用哈希表统计每个元素出现的次数,然后返回出现次数最多的元素。 关键点:
- 使用哈希表统计每个元素的出现次数
- 遍历哈希表,找出出现次数大于n/2的元素
时间复杂度:O(n),其中n是数组长度。 空间复杂度:O(n),需要哈希表存储元素频次。
方法二:Boyer-Moore 投票算法
利用多数元素出现次数大于n/2的特性,使用投票算法来找出多数元素。 关键点:
- 维护一个候选元素
candidate和一个计数器count - 遍历数组,如果
count为0,则将当前元素设为候选元素 - 如果当前元素等于候选元素,则计数器加1,否则减1
- 最终候选元素即为多数元素
时间复杂度:O(n),其中n是数组长度。 空间复杂度:O(1),只需要常数额外空间。
代码实现
C# 实现
方法一:哈希表计数
public class Solution {
public int MajorityElement(int[] nums) {
Dictionary<int, int> counts = new Dictionary<int, int>();
foreach (int num in nums) {
if (!counts.ContainsKey(num)) {
counts[num] = 0;
}
counts[num]++;
}
int majorityCount = nums.Length / 2;
foreach (var pair in counts) {
if (pair.Value > majorityCount) {
return pair.Key;
}
}
return -1; // 不会执行到这里,因为题目保证存在多数元素
}
}
方法二:Boyer-Moore 投票算法
public class Solution {
public int MajorityElement(int[] nums) {
int count = 0;
int candidate = 0;
foreach (int num in nums) {
if (count == 0) {
candidate = num;
}
count += (num == candidate) ? 1 : -1;
}
return candidate;
}
}
Python 实现
方法一:哈希表计数
class Solution:
def majorityElement(self, nums: List[int]) -> int:
counts = {}
for num in nums:
if num not in counts:
counts[num] = 0
counts[num] += 1
majority_count = len(nums) // 2
for num, count in counts.items():
if count > majority_count:
return num
return -1 # 不会执行到这里,因为题目保证存在多数元素
方法二:Boyer-Moore 投票算法
class Solution:
def majorityElement(self, nums: List[int]) -> int:
count = 0
candidate = None
for num in nums:
if count == 0:
candidate = num
count += 1 if num == candidate else -1
return candidate
C++ 实现
方法一:哈希表计数
class Solution {
public:
int majorityElement(vector<int>& nums) {
unordered_map<int, int> counts;
for (int num : nums) {
counts[num]++;
}
int majorityCount = nums.size() / 2;
for (auto& pair : counts) {
if (pair.second > majorityCount) {
return pair.first;
}
}
return -1; // 不会执行到这里,因为题目保证存在多数元素
}
};
方法二:Boyer-Moore 投票算法
class Solution {
public:
int majorityElement(vector<int>& nums) {
int count = 0;
int candidate = 0;
for (int num : nums) {
if (count == 0) {
candidate = num;
}
count += (num == candidate) ? 1 : -1;
}
return candidate;
}
};
性能分析
各语言实现的性能对比(以方法二为例):
| 实现语言 | 执行用时 | 内存消耗 | 特点 |
|---|---|---|---|
| C# | 112 ms | 40.7 MB | 实现简洁,性能适中 |
| Python | 156 ms | 17.6 MB | 代码最简洁 |
| C++ | 16 ms | 19.5 MB | 性能最优 |
补充说明
代码亮点
- 使用Boyer-Moore投票算法,时间复杂度O(n),空间复杂度O(1)
- 哈希表计数法思路清晰,易于理解
- 代码简洁,处理了各种边界情况
常见错误
- 没有正确理解“多数元素”的定义,多数元素是指出现次数大于n/2的元素
- 使用排序后取中间元素的方法,时间复杂度为O(nlogn),不是最优解
- 没有考虑数组中可能有负数