Leetcode 主要元素(摩尔投票法)

本文深入探讨了LeetCode上一道经典题目——寻找数组中的主要元素,即占比超过一半的元素。利用摩尔投票法,文章提供了O(N)时间复杂度和O(1)空间复杂度的高效解决方案,并通过实例讲解了算法原理。

Leetcode 主要元素(摩尔投票法)


数组中占比超过一半的元素称之为主要元素。给定一个整数数组,找到它的主要元素。若没有,返回-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) 内完成吗?

class Solution {
    public int majorityElement(int[] nums) {
        int major=0, cur = 0;//设置标识和票数
        for(int i = 0; i < nums.length; i++){
            if(cur == 0){//如果当前票数为0,则该标识设置为当前数值
                major = nums[i];
            }
            //判断标识是否与当前数值相同,相同则加一,不同则减一
            if(major != nums[i]){
                cur--;
            }else{
                cur++;
            }
        }
        //摩尔投票法中,计算最后票数为正的标识在数组中的个数
        if(cur > 0){
            int t = 0;
            for(int i = 0; i < nums.length ; i++){
                if(nums[i] == major){
                    t++;
                }
            }
            if(t>nums.length/2)
                return major;
        }
        return -1;
    }
    
}

执行结果:
通过
显示详情
执行用时:1 ms, 在所有 Java 提交中击败了100.00% 的用户
内存消耗:43 MB, 在所有 Java 提交中击败了67.71% 的用户

自我总结:摩尔投票法的核心就是“抵消”,通过一对一的方式就多于一半的元素留下来,就是所谓的人海战术。最后留下来的一定是最多的那个。知乎上的详细解释

LeetCode 169题多数元素是要在给定大小为`n`的数组中,找到出现次数大于`⌊ n/2 ⌋`的元素,且假设数组非空且总是存在多数元素。以下是几种Java解法: ### 哈希表法 通过哈希表记录每个元素的出现次数,然后遍历哈希表找出出现次数大于`n/2`的元素。 ```java import java.util.HashMap; import java.util.Map; class Solution { public int majorityElement(int[] nums) { int n = nums.length; Map<Integer, Integer> numMap = new HashMap<>(); for (int i = 0; i < n; i++) { if (numMap.containsKey(nums[i])) numMap.put(nums[i], numMap.get(nums[i]) + 1); else numMap.put(nums[i], 1); } for (Map.Entry<Integer, Integer> entry : numMap.entrySet()) { if (entry.getValue() > n / 2) return entry.getKey(); } return 0; } } ``` 此方法的空间复杂度至少需要额外的`O(n)`空间,因为哈希表最多可能存储`n`个元素[^2][^3]。 ### 另一种哈希表法 同样使用哈希表记录元素出现次数,最后遍历哈希表找出出现次数最多的元素。 ```java import java.util.HashMap; import java.util.Map; class Solution { public int majorityElement(int[] nums) { HashMap<Integer, Integer> map = new HashMap<Integer, Integer>(); int n = nums.length; for(int i = 0; i < n; i++) { int x = nums[i]; map.put(x, map.getOrDefault(x, 0) + 1); } int res = 0; int count = 0; for(Map.Entry<Integer, Integer> entry : map.entrySet()) { if(entry.getValue() > count) { count = entry.getValue(); res = entry.getKey(); } } return res; } } ``` 该方法也使用了哈希表,空间复杂度为`O(n)` [^3]。 ### 摩尔投票法 使用两个临时变量,`vote`用于统计当前累积票数,`x`用于记录当前众数,遍历数组不断更新累积票数和当前众数。 ```java public class N169_MostElements { public static int majorityElementMooreVotes(int[] nums) { int vote = 1; int x = nums[0]; for (int i = 1; i < nums.length; i++) { if (vote == 0) { x = nums[i]; vote++; } else { if (nums[i] != x) { vote--; } else { vote++; } } } return x; } } ``` 这种方法的时间复杂度为`O(n)`,空间复杂度为`O(1)` [^5]。 ### 另一种摩尔投票法实现 ```java class Solution { public int majorityElement(int[] nums) { int count = 1; int maj = nums[0]; for (int i = 1; i < nums.length; i++) { if (maj == nums[i]) count++; else { count--; if (count == 0) { maj = nums[i + 1]; } } } return maj; } } ``` 此实现同样是摩尔投票法,空间复杂度为`O(1)` [^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值