摩尔投票算法--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),只用到了固定数量的变量。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值