当前位置: 首页 > article >正文

摩尔投票算法--169. 多数元素

169. 多数元素

普通方法-借助map计数

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        map<int,int> mp;
        for(int num :nums){
            mp[num]++;
        }
        for(auto &a :mp){
            if(a.second>nums.size()/2){
                return a.first;
            }
        }
        return 0;
    }
};

进阶:尝试设计时间复杂度为 O(n)、空间复杂度为 O(1) 的算法解决此问题。

 

-----摩尔投票:Boyer-Moore 投票算法只能在数组中存在一个多数元素且该元素的出现次数严格超过数组长度的一半时有效。

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int ans=nums[0],count=0;
        for(int i=0;i<nums.size();i++){
            if(count==0) ans=nums[i];
            if(nums[i]==ans)count++;
            else count--;
        }
        return ans;
    }
};

代码逻辑解释:

  1. 初始化

    • ans = nums[0]ans 是当前的候选多数元素,初始化为数组的第一个元素。
    • count = 0count 是计数器,用来记录当前候选元素的优势(即它的相对出现次数)。
  2. 遍历数组

    • for(int i = 0; i < nums.size(); i++):遍历数组中的每个元素。
  3. 判断当前元素是否为候选多数元素

    • if(count == 0) ans = nums[i];:当计数器为 0 时,表示当前没有有效的候选多数元素,因此将当前元素 nums[i] 设为新的候选元素 ans
  4. 更新计数器

    • if(nums[i] == ans) count++;:如果当前元素等于候选元素 ans,增加计数 count
    • else count--:如果当前元素不等于候选元素 ans,减少计数 count
  5. 返回结果

    • 最终返回 ans,即数组中的多数元素。

为什么算法有效?

该算法利用了一个事实:多数元素的出现次数超过了一半,即出现次数比其他所有元素的总和都多。在遍历数组时,每当遇到多数元素时,计数器增加;当遇到其他元素时,计数器减少。当计数器为 0 时,意味着之前的候选元素不再具备多数的可能性,此时更新候选元素为当前元素。

因为多数元素的出现次数超过了数组长度的一半,最终剩下的候选元素一定是多数元素。

举个例子:

假设 nums = [2, 2, 1, 1, 1, 2, 2],我们一步步执行代码:

  • 初始:ans = 2count = 0
  • i = 0:当前元素 2count == 0,设置 ans = 2count++ -> count = 1
  • i = 1:当前元素 2,等于 anscount++ -> count = 2
  • i = 2:当前元素 1,不等于 anscount-- -> count = 1
  • i = 3:当前元素 1,不等于 anscount-- -> count = 0
  • i = 4:当前元素 1count == 0,设置 ans = 1count++ -> count = 1
  • i = 5:当前元素 2,不等于 anscount-- -> count = 0
  • i = 6:当前元素 2count == 0,设置 ans = 2count++ -> count = 1

最后 ans = 2,返回的结果即为多数元素 2

总结:

  • 时间复杂度:O(n),只需遍历数组一次。
  • 空间复杂度:O(1),只用到了固定数量的变量。

 


http://www.kler.cn/a/299077.html

相关文章:

  • Godot RPG 游戏开发指南
  • Golong中无缓冲的 channel 和 有缓冲的 channel 的区别
  • 【Prompt Engineering】6 文本扩展
  • Spring Cloud Gateway 源码
  • 题海拾贝:力扣 86.分隔链表
  • 【C++】C++中的std::cerr详解
  • 部署定时任务每2天清理一次表
  • Kali Linux 设置与维护教程
  • 什么是跨站脚本攻击(XSS)和跨站请求伪造(CSRF)?
  • 大数据之Flink(二)
  • 线程池以及详解使用@Async注解异步处理方法
  • Vue 中的 Web Workers:提升性能与流畅度
  • GDB的使用
  • java基础 | 动态代理
  • 力推高阶智驾普及:埃安再放大招
  • OS 模块常用方法
  • Deploying Spring Boot Apps Tips
  • Java面试题精选:分布式(一)
  • Vue3+setup实现父子组件单表增删改查写法模板
  • 828华为云征文|华为云Flexus X实例docker部署mediacms,功能齐全的现代化开源视频和媒体CMS
  • axure判断
  • k8s HPA
  • 进程查看和计划任务
  • web渗透:RCE漏洞
  • k8s防火墙networkPolicy,的核心是“自己”
  • 苹果首款AI手机发布!iPhone 16全新AI功能体验感拉满