原题
双指针与滑动窗口中等2 种解法

#209长度最小的子数组

在正整数数组中寻找元素和至少为 target 的最短连续子数组,不存在时返回 0。

#数组#滑动窗口#前缀和

原题

给定一个含有 n 个正整数的数组和一个正整数 target

找出该数组中满足其总和大于等于 target 的长度最小的 子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度如果不存在符合条件的子数组,返回 0

示例 1:

输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。

示例 2:

输入:target = 4, nums = [1,4,4]
输出:1

示例 3:

输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0

提示:

  • 1 <= target <= 109
  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 104

进阶:

  • 如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。

查看原题

解题主线

  1. 所有元素均为正数,因此右端加入元素只会让窗口和增大,左端移出元素只会让窗口和减小。
  2. 窗口达到 target 后应持续收缩并记录长度,直到再次不满足条件,才能保证不会遗漏更短答案。
  3. 双重枚举在固定起点后可一边扩展终点一边累加,命中后立即停止该起点的扫描。

解法 1:枚举起点与终点

固定每个起点,向右累加到首次达到 target;因为元素为正,之后只会更长,可以立刻处理下一个起点。

  • 时间复杂度: O(n²)

  • 空间复杂度: O(1)

JAVA
final class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        // Integer.MAX_VALUE 作为“尚未找到可行区间”的哨兵,返回前再转换为 0。
        int minimumLength = Integer.MAX_VALUE;
        // 正数保证固定左端点后区间和单调增加,首次达标即是该起点的最短区间。
        for (int left = 0; left < nums.length; left++) {
            int sum = 0;
            for (int right = left; right < nums.length; right++) {
                sum += nums[right];
                if (sum >= target) {
                    minimumLength = Math.min(minimumLength, right - left + 1);
                    break;
                }
            }
        }
        return minimumLength == Integer.MAX_VALUE ? 0 : minimumLength;
    }
}

解法 2:同向双指针滑动窗口

右指针逐项扩张并累加;窗口和达标时反复移动左指针,在失去可行性前更新最短长度。

  • 时间复杂度: O(n),每个元素最多进入和离开窗口各一次

  • 空间复杂度: O(1)

JAVA
final class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int left = 0;
        int sum = 0;
        int minimumLength = Integer.MAX_VALUE;

        // 窗口 [left, right] 的 sum 与指针移动保持同步,每个元素最多进出一次。
        for (int right = 0; right < nums.length; right++) {
            sum += nums[right];
            // 元素均为正;达标后持续右移 left,才能得到该右端点下的最短可行窗口。
            while (sum >= target) {
                minimumLength = Math.min(minimumLength, right - left + 1);
                sum -= nums[left++];
            }
        }
        return minimumLength == Integer.MAX_VALUE ? 0 : minimumLength;
    }
}

边界与易错点

  • 滑动窗口解法依赖 nums 中都是正整数;若允许负数,窗口和不再具备单调性。
  • 无解时不能返回 Integer.MAX_VALUE,应转换为 0。
  • 连续子数组不能跳过中间元素。

整理来源

由旧仓库源码复核、去重并整理;展示代码已按 Java 21 语义修正明显问题。

  • leetcode/src/main/java/medium/Q209_minSubArrayLen.java