跳到主要内容

多数元素

· 阅读需 5 分钟
Eureka X
Mr.Nobody

力扣面试经典——169题

💡 参考代码:

/**
* 查找数组中的多数元素(出现次数大于⌊n/2⌋的元素)
* 使用Boyer-Moore投票算法实现
*
* @param nums 整数数组指针
* @param numsSize 数组长度
* @return 返回多数元素
*/
int majorityElement(int* nums, int numsSize) {
// 初始化候选人为第一个元素,计数为1
int candidate = nums[0];
int count = 1;

// 投票阶段:遍历数组中剩余的所有元素
for (int i = 1; i < numsSize; i++) {
// 如果计数为0,更换候选人
if (count == 0) {
candidate = nums[i]; // 设置新的候选人
count = 1; // 重置计数为1
}
// 如果当前元素与候选人相同,计数加1
else if (nums[i] == candidate) {
count++;
}
// 如果当前元素与候选人不同,计数减1(相当于抵消)
else {
count--;
}
}

// 返回最终的候选人(多数元素)
return candidate;
}

📖 总结:

点击展开题目总结

🤔 多数元素


1️⃣ 题目核心信息

🎯 功能描述:给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。

📥 输入输出

  • 输入int* nums(整数数组指针),int numsSize(数组长度)
  • 输出:返回多数元素(保证存在)

2️⃣ 实现原理

💡 核心思路:使用Boyer-Moore投票算法,利用多数元素出现次数超过一半的特性,通过"投票抵消"机制找到目标元素。

📋 实现步骤

  1. 初始化候选元素为数组第一个元素,计数器为1
  2. 遍历数组剩余元素
  3. 若计数器为0,更新候选元素为当前元素,计数器重置为1
  4. 若当前元素等于候选元素,计数器加1
  5. 若当前元素不等于候选元素,计数器减1
  6. 返回最终候选元素

3️⃣ 关键点解析

原始思路是使用双重循环统计每个元素出现次数,时间复杂度O(n²),虽然正确但效率低。最优解使用Boyer-Moore投票算法,时间复杂度降为O(n),空间复杂度O(1)。

🎯 代码技巧

  • 利用多数元素超过一半的数学特性
  • 采用抵消思想,相同+1,不同-1
  • 无需实际统计次数,只需找到候选元素

4️⃣ 使用场景

✅ 适用情况:

  • 需要找到出现次数超过一半的元素
  • 数据流中查找多数元素
  • 在线算法场景,需要实时处理

⚠️ 前提条件:

  • 数组非空
  • 保证存在多数元素(出现次数>n/2)

5️⃣ 复杂度分析

  • ⏱️ 时间复杂度:O(n) - 只需遍历数组一次

  • 💾 空间复杂度:O(1) - 只使用常数额外空间

6️⃣ 注意事项

🚩 边界情况:

  • 数组只有一个元素
  • 多数元素刚好出现⌊n/2⌋+1次
  • 数组长度为偶数或奇数的情况

💥 易错点:

  • 忘记处理计数器为0时的候选元素更新
  • 混淆多数元素的判断条件(>n/2而非≥n/2)
  • 在实际应用中未验证结果确实为多数元素

7️⃣ 补充说明

"战场对决"类比

/**
* 多数元素查找 - Boyer-Moore投票算法详解
*
* 核心思想:多数元素的数量超过总数的一半
* 就像一支军队人数超过总兵力的50%,即使与其他所有军队一对一战斗,
* 最后剩下的肯定还是这支军队的人
*/
int majorityElement(int* nums, int numsSize) {
// 初始时,我们假设第一个士兵(数组第一个元素)是我们要找的军队
int candidate = nums[0]; // 当前候选军队
int count = 1; // 当前军队的士兵数量(初始为1)

// 从第二个士兵开始检阅整个军队
for (int i = 1; i < numsSize; i++) {
// 如果战场上没有士兵了(count为0)
if (count == 0) {
// 更换候选军队为当前遇到的士兵所属军队
candidate = nums[i]; // 新的候选军队
count = 1; // 这支军队当前有1个士兵
}
// 如果当前士兵属于我们正在追踪的候选军队
else if (nums[i] == candidate) {
count++; // 该军队士兵数量+1
}
// 如果当前士兵属于其他军队(敌对军队)
else {
count--; // 我们候选军队的士兵与敌军士兵同归于尽,数量-1
}
}

// 最终剩下的候选军队就是多数军队(多数元素)
return candidate;
}

具体例子演示

以数组 [2,2,1,1,1,2,2] 为例:

步骤当前元素candidatecount说明
初始-21假设第一个元素2是多数元素
i=1222遇到相同元素,count++
i=2121遇到不同元素,count--(2和1抵消)
i=3120再次抵消,count变为0
i=4111count为0,更换候选元素为1
i=52101和2抵消,count变为0
i=6221count为0,更换候选元素为2
加载评论中...