剑指 offer 39 数组中出现次数超过一半的数字(摩尔投票法)

1 题目描述

 

2 算法思路

本题常见解法如下:

  • 1.哈希表统计法:遍历数组| nums , 用HashMap统计各数字的数量,最终超过数组长度一半的数字则为众数。 此方法时间和空间复杂度均为O(N)。
  • 2.数组排序法:将数组nums 排序,于众数的数量超过数组长度-半, 因此数组中点的元素-定为众数。仿法时间复杂度O(Nlog2N)。
  • 3.摩尔投票法:核心理念为 “正负抵消”;时间和空间复杂度分别为O(N)和O(1) ;是本题的最佳解法。

摩尔投票法:  假设众数是 x

  •  投票数和:如果当前数是众数,那么投票数 vote++ ,否则 vote--,因为众数大于一半,因此所有数字一定可得,vote > 0 
  • 正负抵消:当 前 n 个数字的vote == 0时,那么就一定可知,后面的vote > 0

思路:

  • 利用正负抵消的性质,我们可以假设第一个元素是众数,然后开始向后遍历
  • 每次遍历后,如果vote ==0,那么就说明,前面的元素可以抛弃不看,后面的vote 一定 大于0
  • 因此每次更新 vote ==0 后的数为众数
    • 如果当前数 真的就是众数,那么一直到末尾的vote > 0
    • 如果当前数不是众数,那么就一直会存在 vo== 0 的时刻,会进行众数更新
  • 利用这种特性,只需要一次遍历即可完成,因此时间复杂度是线性的。

3 代码

class Solution {
    public int majorityElement(int[] nums) {
        int x= 0;
        int vote = 0;
        for(int num : nums){
            if(vote == 0)   //更新众数
                x = num;
            vote += x == num ? 1 : -1;  //如果是众数,就加1,不是就减1
        }
        return x;
    }
}

4 提交结果

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值