
2026-05-09:不同元素和至少为 K 的最短子数组长度。用go语言,给定一个整数数组 nums 和一个整数 k。你需要在数组中找一个连续的非空子数组,使得这个子数组里不同元素的种类数对应的取值之和(也就是:每个数只算一次,不重复计)不小于 k。求满足条件的最短子数组长度;如果不存在这样的子数组,就返回 -1。
1 <= nums.length <= 100000。
1 <= nums[i] <= 100000。
1 <= k <= 1000000000。
输入: nums = [2,2,3,1], k = 4。
输出: 2。
解释:
子数组 [2, 3] 具有不同的元素 {2, 3},它们的和为 2 + 3 = 5,这至少为 k = 4。因此,答案是 2。
题目来自力扣3795。
我们使用滑动窗口(双指针) 算法:用左、右两个指针界定一个连续的窗口,右指针不断向右扩展窗口,把元素加入窗口;当窗口内不同元素的和 ≥ k 时,尝试收缩左指针缩小窗口,同时记录满足条件的最小窗口长度。整个过程只遍历数组一次,保证高效性。
cnt:哈希表,记录窗口内每个数字出现的次数sum:记录窗口内不同元素的和(每个数字只加一次,重复出现不加)left:滑动窗口的左边界指针ans:记录满足条件的最短子数组长度,初始为无穷大i(右指针):滑动窗口的右边界指针数组:[2, 2, 3, 1],目标和 k=4
初始状态:cnt=空,sum=0,left=0,ans=无穷大
cnt[2] = 1sum += 2 → sum=2cnt[2] = 2cnt[3] = 1sum += 3 → sum=5cnt[2] = 1cnt[2] = 0,2 彻底离开窗口cnt[1] = 1sum += 1 → sum=4cnt[3] = 0,3 彻底离开窗口遍历完整个数组后,ans=2(不是无穷大),返回结果 2。
cnt 存储窗口内的不同元素package main
import (
"fmt"
"math"
)
func minLength(nums []int, k int)int {
cnt := map[int]int{}
sum := 0
left := 0
ans := math.MaxInt
for i, x := range nums {
// 1. 入
cnt[x]++
if cnt[x] == 1 {
sum += x
}
for sum >= k {
// 2. 更新答案
ans = min(ans, i-left+1)
// 3. 出
out := nums[left]
cnt[out]--
if cnt[out] == 0 {
sum -= out
}
left++
}
}
if ans == math.MaxInt {
return-1
}
return ans
}
func main() {
nums := []int{2, 2, 3, 1}
k := 4
result := minLength(nums, k)
fmt.Println(result)
}

# -*-coding:utf-8-*-
import math
defminLength(nums, k):
cnt = {}
sum_val = 0
left = 0
ans = math.inf
for i, x inenumerate(nums):
# 1. 入
cnt[x] = cnt.get(x, 0) + 1
if cnt[x] == 1:
sum_val += x
while sum_val >= k:
# 2. 更新答案
ans = min(ans, i - left + 1)
# 3. 出
out_val = nums[left]
cnt[out_val] -= 1
if cnt[out_val] == 0:
sum_val -= out_val
left += 1
if ans == math.inf:
return -1
return ans
if __name__ == "__main__":
nums = [2, 2, 3, 1]
k = 4
result = minLength(nums, k)
print(result)
#include <iostream>
#include <vector>
#include <unordered_map>
#include <climits>
#include <algorithm>
usingnamespace std;
int minLength(vector<int>& nums, int k) {
unordered_map<int, int> cnt;
int sum = 0;
int left = 0;
int ans = INT_MAX;
for (int i = 0; i < nums.size(); i++) {
int x = nums[i];
// 1. 入
cnt[x]++;
if (cnt[x] == 1) {
sum += x;
}
while (sum >= k) {
// 2. 更新答案
ans = min(ans, i - left + 1);
// 3. 出
int out_val = nums[left];
cnt[out_val]--;
if (cnt[out_val] == 0) {
sum -= out_val;
}
left++;
}
}
if (ans == INT_MAX) {
return-1;
}
return ans;
}
int main() {
vector<int> nums = {2, 2, 3, 1};
int k = 4;
int result = minLength(nums, k);
cout << result << endl;
return0;
}
