问题描述
小R从班级中抽取了一些同学,每位同学都会给出一个数字。已知在这些数字中,某个数字的出现次数超过了数字总数的一半。现在需要你帮助小R找到这个数字。
测试样例
样例1:
输入:
array = [1, 3, 8, 2, 3, 1, 3, 3, 3]
输出:3
样例2:
输入:
array = [5, 5, 5, 1, 2, 5, 5]
输出:5
样例3:
输入:
array = [9, 9, 9, 9, 8, 9, 8, 8]
输出:9
def solution(array):
# 摩尔投票算法
candidate = None
count = 0
for num in array:
if count == 0:
candidate = num
count = 1
elif num == candidate:
count += 1
else:
count -= 1
# 验证 candidate 是否真的是众数
count = sum(1 for num in array if num == candidate)
if count > len(array) // 2:
return candidate
else:
return None
if name == "main": # 测试用例 print(solution([1, 3, 8, 2, 3, 1, 3, 3, 3])) # 输出: 3 print(solution([5, 5, 5, 1, 2, 5, 5])) # 输出: 5 print(solution([9, 9, 9, 9, 8, 9, 8, 8])) # 输出: 9 ### 问题描述解析
小R从班级中抽取了一些同学,每位同学都会给出一个数字。已知在这些数字中,某个数字的出现次数超过了数字总数的一半。现在需要你帮助小R找到这个数字。
解题思路
这个问题可以通过 摩尔投票算法(Boyer-Moore Voting Algorithm)来解决。摩尔投票算法的核心思想是在一次遍历中找到一个可能的众数候选,然后再在一次遍历中验证该候选是否确实是众数。具体步骤如下:
-
选择候选众数:
- 遍历数组,维护一个候选众数
candidate和一个计数器count。 - 如果
count为 0,选择当前数字作为新的candidate,并将count设为 1。 - 如果当前数字等于
candidate,则count增加 1。 - 如果当前数字不等于
candidate,则count减少 1。
- 遍历数组,维护一个候选众数
-
验证候选众数:
- 再次遍历数组,统计
candidate的出现次数。 - 如果
candidate的出现次数超过数组长度的一半,则返回candidate,否则返回None。
- 再次遍历数组,统计
代码解析
函数定义
def solution(array):
# 摩尔投票算法
candidate = None
count = 0
for num in array:
if count == 0:
candidate = num
count = 1
elif num == candidate:
count += 1
else:
count -= 1
# 验证 candidate 是否真的是众数
count = sum(1 for num in array if num == candidate)
if count > len(array) // 2:
return candidate
else:
return None
**
选择候选众数
candidate = None
count = 0
for num in array:
if count == 0:
candidate = num
count = 1
elif num == candidate:
count += 1
else:
count -= 1
**
-
初始化
candidate为None,count为 0。 -
遍历数组
array中的每个数字num。- 如果
count为 0,表示当前没有候选众数,选择num作为新的candidate,并将count设为 1。 - 如果
num等于candidate,增加count的值。 - 如果
num不等于candidate,减少count的值。
- 如果
验证候选众数
count = sum(1 for num in array if num == candidate)
if count > len(array) // 2:
return candidate
else:
return None
**
- 再次遍历数组
array,统计candidate的出现次数。 - 使用
sum(1 for num in array if num == candidate)来计算candidate的出现次数。 - 如果
candidate的出现次数大于数组长度的一半,则返回candidate。 - 否则,返回
None。
测试样例解析
-
样例1:
-
输入:
array = [1, 3, 8, 2, 3, 1, 3, 3, 3] -
输出:
3 -
解析:
-
第一次遍历:
num = 1,count = 1,candidate = 1num = 3,count = 0,candidate = 3num = 8,count = 0,candidate = 8num = 2,count = 0,candidate = 2num = 3,count = 0,candidate = 3num = 1,count = 0,candidate = 1num = 3,count = 0,candidate = 3num = 3,count = 1,candidate = 3num = 3,count = 2,candidate = 3
-
第二次遍历验证:
3的出现次数为 5,超过数组长度 9 的一半,因此返回3。
-
-
-
样例2:
-
输入:
array = [5, 5, 5, 1, 2, 5, 5] -
输出:
5 -
解析:
-
第一次遍历:
num = 5,count = 1,candidate = 5num = 5,count = 2,candidate = 5num = 5,count = 3,candidate = 5num = 1,count = 2,candidate = 5num = 2,count = 1,candidate = 5num = 5,count = 2,candidate = 5num = 5,count = 3,candidate = 5
-
第二次遍历验证:
5的出现次数为 4,超过数组长度 7 的一半,因此返回5。
-
-
-
样例3:
-
输入:
array = [9, 9, 9, 9, 8, 9, 8, 8] -
输出:
9 -
解析:
-
第一次遍历:
num = 9,count = 1,candidate = 9num = 9,count = 2,candidate = 9num = 9,count = 3,candidate = 9num = 9,count = 4,candidate = 9num = 8,count = 3,candidate = 9num = 9,count = 4,candidate = 9num = 8,count = 3,candidate = 9num = 8,count = 2,candidate = 9
-
第二次遍历验证:
9的出现次数为 5,超过数组长度 8 的一半,因此返回9。
-
-
总结
摩尔投票算法通过两次遍历数组,第一次寻找可能的众数候选,第二次验证该候选是否确实是众数。该算法的时间复杂度为 O(n),空间复杂度为 O(1),非常高效地解决了众数问题。