题目描述
给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入:nums = [3,2,3]
输出:3
示例 2:
输入:nums = [2,2,1,1,1,2,2]
输出:2
提示:
- n==nums.lengthn == nums.lengthn==nums.length
- 1<=n<=5∗1041 <= n <= 5 * 10^41<=n<=5∗104
- −109<=nums[i]<=109-10^9 <= nums[i] <= 10^9−109<=nums[i]<=109
进阶:尝试设计时间复杂度为 O(n)、空间复杂度为 O(1) 的算法解决此问题。
思考
采用摩尔投票法(Boyer-Moore Voting Algorithm),这是满足“时间复杂度O(n)、空间复杂度O(1)”的最优方案。核心逻辑基于“多数元素出现次数>⌊n/2⌋”的特性:通过“计数抵消”机制,让不同元素两两抵消,最终未被抵消且剩余的元素必然是多数元素(因多数元素数量超过一半,无法被其他元素完全抵消)。
算法过程
-
初始化候选与计数:
- 设
candidate为当前候选的多数元素,初始值为数组第一个元素nums[0]。 - 设
count为候选元素的“剩余计数”,初始值为1(表示当前候选元素有1个未被抵消)。
- 设
-
遍历数组(从第二个元素开始):
- 若
count === 0(当前候选元素已被完全抵消):- 更新
candidate为当前遍历的元素nums[i]。 - 重置
count为1(新候选元素初始计数为1),跳过后续判断。
- 更新
- 若当前元素
nums[i] === candidate(与候选元素相同):count++(候选元素的未抵消数量增加1)。
- 若当前元素
nums[i] !== candidate(与候选元素不同):count--(候选元素与当前元素抵消1次,未抵消数量减少1)。
- 若
-
返回结果:
- 遍历结束后,
candidate即为多数元素(因多数元素无法被完全抵消,必然成为最终候选)。
- 遍历结束后,
时空复杂度分析
- 时间复杂度:O(n),仅需遍历数组一次,每个元素的判断和计数操作均为常数时间(O(1)),总时间与数组长度成正比。
- 空间复杂度:O(1),仅使用
candidate和count两个变量存储状态,无额外依赖与输入规模相关的数据结构(如哈希表、数组),完全满足进阶要求。
代码
/**
* @param {number[]} nums
* @return {number}
*/
var majorityElement = function(nums) {
let candidate = nums[0];
let count = 1;
for (let i = 1; i < nums.length; i++) {
if (count === 0) {
candidate = nums[i];
count = 1;
continue;
}
if (nums[i] === candidate) {
count++;
} else {
count--;
}
}
return candidate;
};
440

被折叠的 条评论
为什么被折叠?



