Skip to main content

229.求众数 II

标签: array, hash-table

难度: Medium

通过率: 53.16%

原题链接: https://leetcode.com/problems/majority-element-ii/description/

题目描述

给定一个大小为 n 的整数数组,找出所有出现次数超过 ⌊ n/3 ⌋ 次的元素。

解题思路

在这道题中,要求找出所有出现在数组中超过 ⌊ n/3 ⌋ 次的元素。可以利用Boyer-Moore投票算法的改进版来实现线性时间和常数空间的解法。`

  1. 算法思路如下:`
  • 首先,我们观察到一个事实:在一个长度为 n 的数组中,出现次数超过 ⌊ n/3 ⌋ 次的元素最多有两个。`
  • 因此,我们可以尝试用两个变量来保存数组中可能出现的超过次数的两个候选元素。`
  • 使用两个变量 candidate1 和 candidate2 分别来记录这两个候选元素,并用 count1 和 count2 来记录它们的计数值。
  1. 实现步骤:`
  • 初始化 candidate1, candidate2 为两个不同的任意值(可以是不在数组中的特殊值,比如 None),count1, count2 都为 0;`
  • 遍历数组中的每个元素:`
    • 如果当前元素等于 candidate1,则增加 count1;`
    • 否则,如果当前元素等于 candidate2,则增加 count2;`
    • 如果 count1 为 0,则将 candidate1 设为当前元素,并把 count1 置为 1;`
    • 否则如果 count2 为 0,则将 candidate2 设为当前元素,并把 count2 置为 1;`
    • 否则,将 count1 和 count2 都减少 1。
  • 第二遍扫描数组以确认这两个候选元素的实际出现次数。`
  • 返回实际出现次数大于 ⌊ n/3 ⌋ 的元素。`

代码实现

def majorityElement(nums):
# 初始化候选元素和计数
candidate1, candidate2, count1, count2 = None, None, 0, 0

# 第一次遍历找到候选者
for num in nums:
if candidate1 == num:
count1 += 1
elif candidate2 == num:
count2 += 1
elif count1 == 0:
candidate1, count1 = num, 1
elif count2 == 0:
candidate2, count2 = num, 1
else:
count1 -= 1
count2 -= 1

# 第二次验证这两个候选者出现的次数
result = []
for candidate in [candidate1, candidate2]:
if nums.count(candidate) > len(nums) // 3:
result.append(candidate)
return result

复杂度分析

时间复杂度为 O(n)O(n),其中 nn 是数组的长度,因为我们最多只需要遍历两次数组。
空间复杂度为 O(1)O(1),因为只使用了固定数量的额外变量。