找出出现次数超过一半的数字 | 豆包MarsCode AI刷题
问题分析
给定一个数组 array,数组中有某个数字的出现次数超过了数字总数的一半。我们的任务是找出这个数字。这个问题涉及到寻找数组中出现频率最高的数字,并且我们知道有且只有一个数字的出现次数超过了数组大小的一半。
思路与方法
-
暴力解法:使用哈希表计数 最直接的解决办法是使用哈希表(或字典)统计每个数字的出现次数,然后找出出现次数最多的数字。具体步骤是:
- 遍历数组,使用哈希表记录每个数字的出现次数。
- 遍历哈希表,查找出现次数大于数组长度一半的数字。
这种方法的时间复杂度是 O(n),其中 n 是数组的长度。空间复杂度是 O(n),因为需要额外存储哈希表中的所有数字及其出现次数。
-
优化方法:摩尔投票算法(Boyer-Moore Voting Algorithm) 由于题目中给出了一个特殊的条件:某个数字的出现次数超过了一半,因此可以使用摩尔投票算法来高效地找到这个数字。摩尔投票算法是一种时间复杂度为 O(n),空间复杂度为 O(1) 的算法,非常适合这个问题。
摩尔投票算法的核心思想
摩尔投票算法的核心思想是通过一次遍历来找出一个候选的众数(出现次数超过一半的数字)。算法的基本思路如下:
- 我们维护一个候选数字和一个计数器。初始化时,候选数字为空,计数器为 0。
- 遍历数组中的每个元素:
- 如果计数器为 0,则将当前数字设为候选数字,计数器加 1。
- 如果当前数字等于候选数字,则计数器加 1。
- 如果当前数字不等于候选数字,则计数器减 1。
- 遍历完成后,候选数字即为出现次数最多的数字。因为题目保证有且仅有一个数字出现次数超过了一半,所以候选数字即为我们需要的答案。
摩尔投票算法的详细步骤
- 初始化:设定两个变量:
candidate用来存储当前的候选数字。count用来存储当前候选数字的计数器。
- 遍历数组:对于数组中的每个数字
num,执行以下操作:- 如果
count为 0,说明当前候选数字的票数已被抵消,那么我们将candidate更新为num,并将count设为 1。 - 如果
num等于当前的candidate,则将count增加 1。 - 如果
num不等于当前的candidate,则将count减少 1。
- 如果
- 返回结果:遍历结束后,
candidate存储的就是我们要找的数字。
时间复杂度与空间复杂度分析
- 时间复杂度:O(n),因为我们只遍历了数组一次。
- 空间复杂度:O(1),因为我们只用了常数空间来存储候选数字和计数器。