leetcode
leetcode 2051 ~ 2100
出现最频繁的偶数元素

出现最频繁的偶数元素

难度:

标签:

题目描述

代码结果

运行时间: 45 ms, 内存: 16.2 MB


/*
 * 思路:
 * 1. 使用Stream API过滤出偶数。
 * 2. 使用Collectors.groupingBy统计每个偶数的出现次数。
 * 3. 找到出现次数最多且最小的偶数。
 */

import java.util.Arrays;
import java.util.Comparator;
import java.util.Map;
import java.util.stream.Collectors;

public class MostFrequentEvenStream {
    public int mostFrequentEven(int[] nums) {
        return Arrays.stream(nums)
                     .filter(num -> num % 2 == 0) // 过滤偶数
                     .boxed() // 转为对象流
                     .collect(Collectors.groupingBy(num -> num, Collectors.counting())) // 统计出现次数
                     .entrySet()
                     .stream()
                     .max(Map.Entry.comparingByValue(Comparator.comparingLong(count -> count))
                          .thenComparing(Map.Entry.comparingByKey())) // 比较次数和数值
                     .map(Map.Entry::getKey)
                     .orElse(-1); // 如果没有偶数返回-1
    }
}

解释

方法:

此题解首先通过列表推导过滤出数组中的所有偶数元素,存入列表 new。若 new 为空,则直接返回 -1,表示没有偶数元素。接下来,使用 Counter 来统计 new 中每个元素的出现频次。通过遍历这些元素及其频次,维护一个变量 curr 来记录当前出现最频繁的偶数元素,初始值设为 2001,超过数组元素的最大可能值,以便于更新。同时,使用 freq 变量记录最大频次。在遍历过程中,如果发现更高的频次,则更新 curr 和 freq。如果发现相同的频次,比较并更新 curr 为更小的偶数。最终返回 curr,即为出现最频繁的最小偶数元素。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
在解题思路中,为何选择使用列表推导来过滤偶数,而不是在后续处理中直接判断?这样做有什么优点或缺点?
使用列表推导来过滤偶数可以简化后续的代码逻辑,因为这样做可以直接生成包含所有需要处理的偶数的新列表。这种方法的优点是代码更清晰、易于理解,并且可以减少后续操作中的条件判断,提高效率。缺点包括可能增加内存使用,因为需要额外存储过滤后的偶数列表,特别是当原始数组很大且偶数占比较高时。
🦆
在更新最频繁的偶数元素时,curr初始设置为2001,这种选择的依据是什么?是否有更合理的初始值设置方法?
curr初始设置为2001是为了确保在后续遍历中,任何一个实际出现的偶数都会比这个初始值小,从而能够在首次比较时被更新。这种方法简化了代码逻辑,避免了处理特殊情况或额外的条件判断。更合理的方法可能是使用Python的float('inf')作为初始值,这是一个表示无限大的值,可以更清楚地表达“比任何数都大”的意图,而且不依赖于具体数值范围。
🦆
题解中如果多个偶数出现频次相同,选择较小的偶数。这里是否有可能通过一次遍历同时解决频次统计和最小值的问题,从而优化代码?
是的,可以通过一次遍历来同时解决频次统计和找到最小值的问题。在遍历nums数组时,可以直接使用一个字典来统计偶数的频率,并同时更新当前最频繁且最小的偶数。这种做法减少了对列表的额外迭代,同时在统计频次的同时即时更新当前最优解,提高了效率和代码的简洁性。

相关问题