面试题 17.10. 主要元素

题目

数组中占比超过一半的元素称之为主要元素。给你一个 整数 数组,找出其中的主要元素。若没有,返回 -1 。请设计时间复杂度为 O(N) 、空间复杂度为 O(1) 的解决方案。

示例 1:

输入:[1,2,5,9,5,9,5,5,5]
输出:5
示例 2:

输入:[3,2]
输出:-1
示例 3:

输入:[2,2,1,1,1,2,2]
输出:2

解题思路

摩尔投票理解

对于[1,2,5,9,5,9,5,5,5],主要元素为5,可以想象成元素被分成了两拨,一波是主要元素,一波是非主要元素。
假设元素之间两两相互抵消

  • 在最坏的情况下,所有非主要元素和主要元素两两相互抵消,最后应该会剩下一个主要元素
  • 在最好情况下,非主要元素之间互相残杀,先把非主要元素内部的元素尽量抵消掉,然后再去与主要元素抵消,最后剩下的主要元素>1
  • 所以即使在最坏的情况下,仍然最少会剩下一个主要元素的
  • 所以我们假设主要元素是can,cnt代表can元素与非主要元素抵消后,can元素还剩多少个,当cnt==0时,说明当前的can元素已经被全部抵消掉了,需要重新设定新的can元素
  • 因为使用can记录了当前主要元素,所以可以防止相同元素之前互相残杀

代码

class Solution {
    public int majorityElement(int[] nums) {

        int can=-1,cnt=0,res=0;
        for (int num : nums) {
            if(cnt==0)
            {
                can=num;
            }
            if(num==can)
            {
                cnt++;
            }else {
                cnt--;
            }
        }
        for (int num : nums) {
            if(num==can)
                res++;
        }
        return res>=(int)(Math.floor((double)nums.length/2)+1)?can:-1;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值