题目
方法一:字典统计法
思路
通过哈希表(字典)统计每个数字的出现次数,并实时更新出现次数最多的数字
-
遍历数组,用字典记录每个数字的出现次数。
-
每次更新字典时,检查当前数字的次数是否超过当前假定答案的次数。如果超过,则更新答案为当前数字。
-
遍历完成后,返回最终答案(即出现次数最多的数字)。
代码
def solution(array):
# Edit your code here
ans = array[0]
my_dict = {}
for element in array:
if element not in my_dict:
my_dict[element] = 1
else:
my_dict[element] += 1
if (my_dict[element] > my_dict[ans]):
ans = element
return ans
if __name__ == "__main__":
# Add your test cases here
print(solution([1, 3, 8, 2, 3, 1, 3, 3, 3]) == 3)
复杂度
- 时间复杂度
- 空间复杂度 ,最坏的情况下数组中所有数字都不重复,需要 的额外空间
方法二:摩尔投票法
注意到,题目中有一个条件是,某个数字的出现次数超过了数字总数的一半。然后这个条件在方法一中没有被使用,方法一更为通用,同时意味着有更好的解法。
摩尔投票法
摩尔投票法又称多数投票算法,是一种用来寻找一组元素中占多数元素的常数空间复杂度()、线性时间复杂度()算法。这一算法应用的问题原型是在集合中寻找可能存在的多数元素,这一元素在输入的序列重复出现并占到了序列元素的一半以上。
思路
摩尔投票法的核心思路是抵消策略:如果一个数字的出现次数超过数组长度的一半,那么将它与其他数字一一抵消,最终剩下的数字必定是这个数字。
分为两阶段实现:
-
第一阶段:通过遍历数组找到候选元素。
-
第二阶段:验证候选元素是否真的超过数组长度的一半(只有在题目未明确保证存在满足条件的元素时需要验证)。
代码
def solution(array):
# Edit your code here
# 第一阶段:找出候选元素
candidate = None
count = 0
for num in array:
if count == 0: # 如果计数为0,更新候选元素
candidate = num
count = 1
elif num == candidate: # 如果当前元素等于候选元素,计数+1
count += 1
else: # 否则,计数-1
count -= 1
# 第二阶段:验证候选元素是否满足条件(此题可以直接return candidate)
count = 0
for num in array:
if num == candidate:
count += 1
return candidate if count > len(array) // 2 else None
if __name__ == "__main__":
# Add your test cases here
print(solution([1, 3, 8, 2, 3, 1, 3, 3, 3]) == 3)
复杂度
-
时间复杂度:
- 第一阶段遍历数组一次:。
- 第二阶段验证候选元素(必要时):,当然这题直接
return candidate即可。 - 总体时间复杂度:。
-
空间复杂度:
- 只使用常数额外空间:。
总结
- 如果明确保证一定存在众数,且数据规模较大,使用摩尔投票法。
- 如果不确定众数是否存在,或者更追求实现简单,使用字典统计方法。