不同元素和至少为 K 的最短子数组长度-LeetCode
3795. 不同元素和至少为 K 的最短子数组长度
🎯 问题描述(来源于LeetCode)
描述:
给定一个整数数组 nums 和一个整数 k。你需要找一个连续的非空子数组,使得该子数组中不同元素的和(即去重后的元素之和)至少为 k。
返回满足条件的最短子数组长度。如果不存在这样的子数组,返回 -1。
说明:
- 子数组必须连续。
- 求和时,重复出现的元素只计算一次。
- 子数组中可以包含重复元素。
示例:
- 示例 1:
1 | 输入: nums = [1,2,3,1,1], k = 5 |
- 示例 2:
1 | 输入: nums = [2,3,1,2,4,3], k = 7 |
- 示例 3:
1 | 输入: nums = [1,1,1,1], k = 2 |
💻 解题思路
思路:滑动窗口(双指针)+ 哈希表统计频率
算法步骤
- 初始化左指针
left = 0,频率字典freq(记录窗口内每个元素的出现次数),变量distinct_sum(记录窗口内不同元素的数值之和)。 - 初始化最小长度
min_len = inf。 - 遍历右指针
right,将nums[right]加入窗口:- 如果该元素在窗口内首次出现(
freq[num] == 0),则将该元素的值加到distinct_sum。 - 更新频率
freq[num] += 1。
- 如果该元素在窗口内首次出现(
- 当
distinct_sum >= k时,尝试缩小窗口:- 更新
min_len = min(min_len, right - left + 1)。 - 将左指针元素移出窗口:
freq[nums[left]] -= 1。 - 如果该元素的频率变为 0,则从
distinct_sum中减去该元素的值。 - 左指针右移
left += 1。
- 更新
- 若
min_len仍为inf,返回-1;否则返回min_len。
代码实现(您的代码)
1 | from collections import Counter |
📊 性能分析
- 时间复杂度:,每个元素最多被左右指针各访问一次。
- 空间复杂度:,最坏情况下频率字典存储所有不同元素。
思考
本题是 LeetCode 209「长度最小的子数组」的变体,核心区别在于求和规则从“所有元素之和”变为“不同元素之和”。您的代码通过 freq 字典精确控制 distinct_sum 的增减,正确地处理了重复元素。
关键点:
- 进窗口:只有元素首次出现时才加入
distinct_sum。 - 出窗口:只有当元素频率降为 0 时才从
distinct_sum中减去。 - 更新答案:在
while循环内(即满足条件时)不断收缩窗口并更新最小长度。
该解法是本题的标准滑动窗口实现,逻辑清晰,能够通过所有测试用例。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 笺札!






