问题描述
小R从班级中抽取了一些同学,每位同学都会给出一个数字。已知在这些数字中,某个数字的出现次数超过了数字总数的一半。现在需要你帮助小R找到这个数字。
测试样例1
输入:`array = [1, 3, 8, 2, 3, 1, 3, 3, 3]`
输出:`3`
测试样例2
输入:`array = [5, 5, 5, 1, 2, 5, 5]`
输出:`5`
问题分析
问题特点
- 已知条件:存在一个数字,其出现次数超过了总数字数目的一半。
- 求解目标:找到这个多数元素
- 限制条件:要求高效地找到结果;不能使用过多的额外空间。
思路与解法
-
暴力法
最简单的思路是统计每个数字的出现次数,找到出现次数超过总数一半的数字。即用一个哈希表统计每个数字出现的次数,再直接返回出现次数大于总数字个数一半的数字。这种方法虽简单,但在空间效率上不是最优。
-
排序法
将所有数字排序,由于多数元素的个数> n/2,因此这个多数元素不管是最小的元素,还是最大的元素,都至少有一个数位于排序后数组的中间位置。因此只需要将数组排序,然后直接return arr[n/2]即可。这种方法的时间复杂度还是高于最优解,但空间复杂度较低。
-
Boyer-Moore 多数投票算法
这是解决该问题的最优解法,采用贪心策略,使用一个计数器记录当前候选元素的优势票数。
这个算法的核心是:
- 选择一个候选数字,初始计数器设为1。
- 遍历数组,如果当前数字与候选数字相同,计数器加1;否则计数器减1。
- 如果计数器减到0,选择当前数字作为新的候选数字,计数器重置为1。
- 遍历结束后,候选数字即为多数元素。
参考代码
def find_majority_element(nums):
# Boyer-Moore 投票算法
candidate = None
count = 0
# 第一遍遍历找到候选数字
for num in nums:
if count == 0:
candidate = num
count += (1 if num == candidate else -1)
# 验证候选数字是否为多数元素
if nums.count(candidate) > len(nums) // 2:
return candidate
else:
return None
# 示例
nums = [3, 3, 4, 2, 3, 3, 3]
result = find_majority_element(nums)
print(result) # 输出3
多数元素问题是一个经典的数组处理问题,其最佳解法是Boyer-Moore多数投票算法。该算法通过一次线性扫描和常数空间实现了高效求解,适合大规模数据处理。在实际应用中,可以根据问题规模选择不同的解法,但Boyer-Moore算法通常是首选方案。