题目描述
给定一个含有 n 个正整数的数组和一个正整数 target。找出该数组中满足其总和大于等于 target 的长度最小的子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
示例:
- 输入:target = 7, nums = [2,3,1,2,4,3]
- 输出:2
- 解释:子数组 [4,3] 是该条件下的长度最小的子数组。
解题思路
这道题是典型的'滑动窗口'应用场景。核心思想是利用两个指针维护一个动态窗口,通过移动左右边界来寻找满足条件的最短区间。
双指针逻辑
我们定义 left 和 right 两个指针,初始都指向数组头部。
- 右指针扩张:不断向右移动
right,将新元素加入当前窗口的和中。 - 左指针收缩:一旦窗口内的和
sum大于或等于target,说明当前窗口可能是一个候选答案。此时尝试向右移动left指针,缩小窗口,同时更新最小长度。只要sum依然满足条件,就继续收缩,直到sum小于target为止。 - 记录结果:在收缩过程中,每次满足条件时都记录当前的窗口长度
right - left + 1,并与历史最小值比较。
这种方法的时间复杂度是 O(n),因为每个元素最多被访问两次(一次由 right 加入,一次由 left 移除)。
代码实现
下面是基于 Java 的实现,重点在于内层 while 循环的处理时机。
public int minSubArrayLen(int target, int[] nums) {
int n = nums.length;
int sum = 0;
int len = Integer.MAX_VALUE;
// 左右指针初始化
for (int left = 0, right = 0; right < n; right++) {
// 1. 扩展窗口:将右侧元素加入总和
sum += nums[right];
// 2. 收缩窗口:当满足条件时,尝试缩小左侧以找到更短的子数组
while (sum >= target) {
len = Math.min(len, right - left + );
sum -= nums[left++];
}
}
len == Integer.MAX_VALUE ? : len;
}


