leetcode
leetcode 1651 ~ 1700
每个子数组的数字种类数

每个子数组的数字种类数

难度:

标签:

题目描述

代码结果

运行时间: 159 ms, 内存: 34.2 MB


import java.util.*;
import java.util.stream.Collectors;

public class DistinctNumbersInSubarraysStream {
    // 方法: 使用Java Stream计算每个子数组的数字种类数
    public int[] distinctNumbers(int[] nums, int k) {
        // 用来存储结果的数组
        int[] result = new int[nums.length - k + 1];
        // 初始化窗口并计算初始种类数
        Set<Integer> set = Arrays.stream(nums, 0, k).boxed().collect(Collectors.toSet());
        result[0] = set.size();
        // 滑动窗口
        for (int i = k; i < nums.length; i++) {
            // 移除左边界的元素
            set.remove(nums[i - k]);
            // 添加右边界的元素
            set.add(nums[i]);
            // 记录结果
            result[i - k + 1] = set.size();
        }
        return result;
    }
}

解释

方法:

该题解采用了滑动窗口的方法来解决问题。首先,利用一个字典来记录每个窗口中的元素及其对应的出现次数。初始化时,填充第一个窗口,并计算其中不同数字的数量,即字典的键的数量。随后,窗口开始向右滑动,每次移动时,从字典中减去左边界的元素计数,并可能将其删除(如果计数为0)。同时,添加新的右边界元素到字典中。每次滑动后,字典的大小(即不同数字的数量)被记录到结果列表中。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
在该算法中,当一个数字的出现次数减到0时你选择从字典中删除它,这种做法的优点是什么?
从字典中删除出现次数为0的数字可以减少字典的大小,这样可以节省空间并提高查询和更新操作的效率。此外,这种做法可以直接使用字典的键的数量来确定窗口中不同数字的种类数,从而简化了求解过程。
🦆
该解法中提到的滑动窗口的边界处理是否考虑了所有可能的边界情况,比如数组长度小于窗口长度k的情况?
在提供的解法中,并没有明确处理数组长度小于窗口长度k的情况。如果数组长度小于k,初始化窗口的循环将会导致索引越界错误。因此,解法应该在开始时添加一个检查,确保k不大于数组长度,以处理这种边界情况。
🦆
滑动窗口算法中,如果数组中存在重复元素对窗口中元素种类数量的计算有什么影响?
在滑动窗口算法中,字典用于记录每个数字的出现次数。即使数组中有重复元素,也不会影响窗口中元素种类数量的计算,因为字典的键是唯一的。重复元素只会增加特定键的计数,但不会增加字典的键的总数,因此种类数仍然准确。

相关问题