Article / 文章

LeetCode 第169题:多数元素

给定一个大小为 n 的数组 nums,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。 你可以假设数组是非空的,并且给定的数组总是存在多数元素。

题目描述

给定一个大小为 n 的数组 nums,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在多数元素。

难度

简单

题目链接

点击在LeetCode中查看题目

示例

示例 1:

输入:nums = [3,2,3]
输出:3

示例 2:

输入:nums = [2,2,1,1,1,2,2]
输出:2

提示

  • n == nums.length
  • 1 <= n <= 5 * 10^4
  • -10^9 <= nums[i] <= 10^9

解题思路

方法一:哈希表计数

使用哈希表统计每个元素出现的次数,然后返回出现次数最多的元素。 关键点:

  1. 使用哈希表统计每个元素的出现次数
  2. 遍历哈希表,找出出现次数大于n/2的元素

时间复杂度:O(n),其中n是数组长度。 空间复杂度:O(n),需要哈希表存储元素频次。

方法二:Boyer-Moore 投票算法

利用多数元素出现次数大于n/2的特性,使用投票算法来找出多数元素。 关键点:

  1. 维护一个候选元素candidate和一个计数器count
  2. 遍历数组,如果count为0,则将当前元素设为候选元素
  3. 如果当前元素等于候选元素,则计数器加1,否则减1
  4. 最终候选元素即为多数元素

时间复杂度: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 性能最优

补充说明

代码亮点

  1. 使用Boyer-Moore投票算法,时间复杂度O(n),空间复杂度O(1)
  2. 哈希表计数法思路清晰,易于理解
  3. 代码简洁,处理了各种边界情况

常见错误

  1. 没有正确理解“多数元素”的定义,多数元素是指出现次数大于n/2的元素
  2. 使用排序后取中间元素的方法,时间复杂度为O(nlogn),不是最优解
  3. 没有考虑数组中可能有负数

相关题目