leetcode169多数元素C++
[!NOTE]
以下内容包含Chatgpt的帮助
题目描述
给定一个大小为 n 的数组 nums,找出其中出现次数超过 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例
示例 1:
输入: nums = [3,2,3] |
示例 2:
输入: nums = [2,2,1,1,1,2,2] |
进阶要求
- 你能在时间复杂度 O(n)、空间复杂度 O(1) 的条件下完成算法吗?
解法 1:哈希表(map 计数)
思路
我们可以使用哈希表(unordered_map)统计每个元素出现的次数,然后找到出现次数超过 ⌊ n/2 ⌋ 的元素。
代码
|
复杂度分析
- 时间复杂度:O(n),遍历数组一次统计出现次数。
- 空间复杂度:O(n),哈希表存储了最多
n个不同的数。
解法 2:排序
思路
- 由于多数元素的出现次数超过
⌊ n/2 ⌋,如果我们对数组进行排序,中间的元素(索引n/2处)一定是多数元素。 - 直接返回
nums[n/2]。
代码
|
复杂度分析
- 时间复杂度:O(n log n)(排序的开销)。
- 空间复杂度:O(1)(原地排序)。
解法 3:摩尔投票法
思路
- 由于多数元素出现的次数超过
⌊ n/2 ⌋,如果我们用一个count计数器,每次遇到相同的元素就加一,不同的元素就减一:count == 0时,我们假设当前元素是多数元素,并将count设为 1。- 继续遍历,最后剩下的
candidate就是多数元素。
代码
|
复杂度分析
- 时间复杂度:O(n),遍历数组一次即可确定多数元素。
- 空间复杂度:O(1),只使用了额外的变量
candidate和count。
摩尔投票法的直觉
- 假设
x是多数元素,y是非多数元素。 - 多数元素的数量 > 其他所有元素的总和,所以最终
x一定会占据主导地位。
数学证明
假设多数元素是M,它出现了 k > n/2 次
假设整个数组长度为 n,其他所有元素的数量是 n - k < k。
- 最坏情况下,
M与其他元素交错排列M, X, M, X, M, X, M, X, M, ...
- 由于
M的数量比X多,在投票过程中M仍然会剩余。 - 假设
X们全部抵消M,但M仍然有k - (n - k) = 2k - n个存活,而X被完全抵消。 - 因为
k > n/2,所以2k - n > 0,即M仍然剩下,最终成为candidate。
- 由于
- 无论
M如何分布,它都不会被完全抵消- 设
M的出现次数为x,所有其他元素的出现次数总和为y。 - 由于
x > y,在遍历的过程中,M可能会被y抵消掉y次,但M仍然剩余x - y次。 - 因此,最终
M仍然是最多的,且一定会成为candidate。
- 设