leetcode
leetcode 1601 ~ 1650
求出 MK 平均值

求出 MK 平均值

难度:

标签:

题目描述

代码结果

运行时间: 541 ms, 内存: 50.6 MB


/*
 * MKAverage class implementation in Java using Java Stream API
 *
 * Thought Process:
 * 1. Initialize the class with m and k values and an empty list to store the stream.
 * 2. For addElement method, add the element to the stream.
 * 3. For calculateMKAverage method, check if the stream has at least m elements.
 *    - If not, return -1.
 *    - Otherwise, get the last m elements, sort them, remove the smallest k and largest k elements, and calculate the average of the remaining elements using streams.
 *    - Return the average after flooring it.
 */
import java.util.*;
import java.util.stream.*;

public class MKAverage {
    private int m, k;
    private List<Integer> stream;

    public MKAverage(int m, int k) {
        this.m = m;
        this.k = k;
        this.stream = new ArrayList<>();
    }

    public void addElement(int num) {
        stream.add(num);
    }

    public int calculateMKAverage() {
        if (stream.size() < m) {
            return -1;
        }
        List<Integer> lastMElements = stream.stream()
                .skip(stream.size() - m)
                .sorted()
                .collect(Collectors.toList());
        for (int i = 0; i < k; i++) {
            lastMElements.remove(0); // Remove smallest k elements
            lastMElements.remove(lastMElements.size() - 1); // Remove largest k elements
        }
        int sum = lastMElements.stream().mapToInt(Integer::intValue).sum();
        return sum / lastMElements.size(); // Floor division
    }
}

解释

方法:

该题解采用了三个有序列表(SortedList)和一个队列(deque)来维护数据流中的最后m个元素,并且实现了动态地维持这些元素中最小的k个、最大的k个和中间的m-2k个元素。每次添加新元素时,首先判断其应该插入哪个有序列表中,并且相应地更新这些列表和中间元素的和。当元素总数超过m时,从队列和相应的有序列表中移除最早的元素,并保持有序列表的平衡。计算MK平均值时,如果元素个数不足m,则返回-1;否则,返回中间元素和的整数除以中间元素的数量。

时间复杂度:

O(log m)

空间复杂度:

O(m)

代码细节讲解

🦆
如何确保在调整三个有序列表的大小时,他们始终保持正确的长度和元素顺序?
保持三个有序列表的正确长度和元素顺序需要通过细心的管理元素添加和删除过程。首先,当元素被添加到系统中时,根据其与现有元素的比较,决定将其添加到最小值列表、最大值列表或中间值列表中。如果列表长度超过预定长度,将从一个列表的端点移动元素到另一个列表以确保所有列表保持正确的长度。例如,如果最小值列表超过了k个元素,将其最大的元素移动到中间值列表。此外,当元素从系统中删除(如从数据流中移除最老的元素)时,也需要检查并从相应的列表中移除该元素,之后再次调整列表以保持正确的长度。这个过程确保了每个列表都能在动态变化的情况下保持其应有的性质和顺序。
🦆
当从中间列表移动元素到上层或下层列表时,为何选择移动中间列表的首元素或尾元素,这种选择对平均值计算有何影响?
从中间列表移动元素到上层或下层列表时选择首元素或尾元素是为了维持列表的有序状态和逻辑一致性。具体来说,若需要向下层列表(存储较小元素)添加元素,应从中间列表的首部移动最小的元素;若需要向上层列表(存储较大元素)添加元素,则从中间列表的尾部移动最大的元素。这样做可以确保中间列表始终维持在正确的范围内,即不包括目前数据流中最大和最小的k个元素。这种选择直接影响到平均值的计算,因为它决定了哪些元素被纳入计算平均值的范围内,从而可能影响最终的平均值结果。
🦆
在删除元素时,如何处理存在于三个有序列表之一中的情况,特别是当相同的元素值可能属于不同列表时?
在删除元素时,首先确定该元素属于哪一个列表。这可以通过比较待删除元素与各列表中的元素范围进行判断。如果元素在最小值列表范围内,则从最小值列表中删除;如果在最大值列表范围内,则从最大值列表中删除;否则,从中间列表中删除。如果相同的元素值可能属于不同的列表,需要根据实际的元素位置和其在数据流中的状态来进行精确的管理。例如,如果一个值既可能是最小值列表中的最大值也可能是中间列表中的最小值,应基于元素在数据流中的顺序和列表的实际需求来决定从哪个列表中删除。这确保了即使在面对重复值时,列表的整体结构和计算逻辑也能保持正确无误。

相关问题