209. 长度最小的子数组(LeetCode)

题目描述


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

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

示例 1:

输入:target = 7, nums = [2,3,1,2,4,3]

输出:2

解释:子数组 [4,3] 是该条件下的长度最小的子数组。

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

条件分析


  1. 要求长度最小;
  2. 数组是连续子数组

解题思路(滑动窗口)


  1. 定义连续子数组的下标分别为i和j,则如果存在解,则解的值为j-i+1,并记录长度;
  2. 如果和大于target,记录当前长度,与之前长度相比取最小值,且i需要增加(缩小范围),否则j需要增加(增大范围);
  3. 如果j已经遍历到了末尾,则等待i增加来缩小范围,如果缩小范围发现小于target,此时j无法增大,说明范围内已经没有解,此时退出循环,因此可以得到循环退出的条件为j<nums.length

编码如下

public int minSubArrayLen(int target, int[] nums) {
    int i = 0; // [i,j]保存最小连续子数组
    int j = -1; // 初始范围内没有解
    int min = nums.length + 1;// 定义一个最小的长度值为不可能的值,即数组的长度+1
    int sum = 0;
    while (j<nums.length) {
        if (sum >= target) {
            min = min(min, j-i+1);
            sum -= nums[i];
            i++;
        } else {
            j++;
            if (j < nums.length) {
                sum += nums[j];
            }
        }
    }
    if (min == nums.length + 1) { // 此时最小值还是初始值,说明没有解
        min = 0;
    }
    return min;
}

private int min(int min, int newMin) {
    if (newMin < min) {
        min = newMin;
    }
    return min;
}
posted @ 2021-07-08 20:02  咸与维新  阅读(56)  评论(0)    收藏  举报