LeetCode刷题-主要元素

本文介绍如何利用Boyer-Moore投票算法解决数组中占比超过一半的主要元素查找问题。通过遍历和计数,实现时间复杂度为O(N)和空间复杂度为O(1)的解决方案,并通过实例和分析详细讲解了算法原理和代码实现。
摘要由CSDN通过智能技术生成

前言说明

算法学习,日常刷题记录。

题目连接

主要元素

题目内容

数组中占比超过一半的元素称之为主要元素。给你一个 整数数组,找出其中的主要元素。若没有,返回-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

分析过程

要注意这里要求时间复杂度为O(N)、空间复杂度为O(1),所以不能用哈希表来处理,必须用其他方法。

可以利用摩尔投票算法,英文名叫Boyer-Moore投票算法,统计数量最多的元素。

遍历数组,当统计数量为0时,把当前元素假定为数量最多的元素,统计数量加1。

后面继续遍历,如果后面的元素和当前元素相等,统计数量继续加1,如果不相等,统计数量减1,等于说相互抵消掉,这个元素有1个,那个元素有1个,那么他们数量相等,而这里是要统计数量最多的元素,所以他们就两两抵消。

后面继续遍历,如果统计数量又变回0了,继续上面的操作,直到遍历数组结束。

最后如果统计数量为0,那么没有数量最多的元素(这里不包括数量重复的元素),因为全部被两两抵消了,如果统计数量大于0,那么找到了数量最多的元素。

例如数组:[1,2,5,9,5,9,5,5,5]

1和2相互抵消,5和9相互抵消,5和9相互抵消,5和5相互抵消,最后找到的元素是5。

若数量count等于0,没有数量最多的元素(这里不包括数量重复的元素),这里找到的元素是最后被两两抵消掉的元素的第一个,但是不可能出现主要元素存在前面的情况,因为主要元素是指数量占比超过一半的元素,如果前面存在主要元素,后面是不可能有被两两抵消掉的,因为主要元素已经占了超过一半,后面的数量不够一半了,所以前面的元素肯定是被两两抵消掉了,那么由此就推出前面不存在主要元素。

若数量count大于0,找到数量最多的元素。

找到数量最多的元素后,开始统计数量最多元素的数量,通过遍历数组nums来统计。

最后若找到元素的数量超过一半,那么就是主要元素,返回找到的元素find,否则就是没有主要元素,返回-1。

解答代码

class Solution {
    public int majorityElement(int[] nums) {
        // 利用摩尔投票算法,统计数量最多的元素
        // 遍历数组,当统计数量为0时,把当前元素假定为数量最多的元素,统计数量加1,后面继续遍历,如果后面的元素和当前元素相等,统计数量继续加1,如果不相等,统计数量减1,等于说相互抵消掉,这个元素有1个,那个元素有1个,那么他们数量相等,而这里是要统计数量最多的元素,所以他们就两两抵消,后面继续遍历,如果统计数量又变回0了,继续上面的操作,直到遍历数组结束,最后如果统计数量为0,那么没有数量最多的元素(这里不包括数量重复的元素),因为全部被两两抵消了,如果统计数量大于0,那么找到了数量最多的元素

        // 定义找到的元素
        int find = -1;
        // 定义找到元素的数量
        int count = 0;

        // 遍历数组nums,找出数量最多的元素
        for (int num : nums) {
            if (count == 0) {
                // 若数量为0,找到的元素设置为当前元素
                find = num;
            }

            if (num == find) {
                // 若当前元素和找到的元素相等,数量加1
                ++count;
            } else {
                // 若当前元素和找到的元素不相等,数量减1
                --count;
            }
        }

        // 至此找到了数量最多的元素,若数量count等于0,没有数量最多的元素(这里不包括数量重复的元素),这里找到的元素是最后被两两抵消掉的元素的第一个,但是不可能出现主要元素存在前面的情况,因为主要元素是指数量占比超过一半的元素,如果前面存在主要元素,后面是不可能有被两两抵消掉的,因为主要元素已经占了超过一半,后面的数量不够一半了,所以前面的元素肯定是被两两抵消掉了,那么由此就推出前面不存在主要元素;若数量count大于0,找到数量最多的元素

        // 找到元素的数量重置为0
        count = 0;

        // 遍历数组nums,统计数量最多的元素的数量
        for (int num : nums) {
            if (num == find) {
                ++count;
            }
        }

        // 若找到元素的数量超过一半,那么就是主要元素,返回找到的元素find,否则就是没有主要元素,返回-1
        return count * 2 > nums.length ? find : -1;
    }
}

提交结果

执行用时1ms,时间击败100.00%的用户,内存消耗44.1MB,空间击败33.45%的用户。

运行结果

原文链接

原文链接:主要元素

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值