240919-LCR008 长度最小子数组

34 阅读1分钟

给定一个含有 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] <= 105

进阶:

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

思路

直接想法是穷举所有可能的子数组来筛选结果——连续、最值等特性想到了穷举的优化法——滑动窗口

同样的,右指针不断加入元素到窗口直到达到临界值curSum >= target,此时开始内循环收缩左边界以求得本窗口内符合条件的最小子数组直到条件破裂后,继续移动右指针寻找下一个符合条件的窗口。

本题相对76更加简单

public int minSubArrayLen(int target, int[] nums) {
    //连续 最小,穷举法的优化--滑动窗口
    int left = 0;
    int right = 0;
    //记录窗口大小
    int minLength = Integer.MAX_VALUE;
    int minIndexBegin = 0;
    //记录此时的窗口之和
    int curSum = 0;

    while(right < nums.length){
        curSum += nums[right];

        while (curSum >= target){
            //收缩左边界
            minIndexBegin = (right - left + 1) < minLength ? left : minIndexBegin;
            minLength = (right - left + 1) < minLength ? (right - left + 1) : minLength;
            curSum -= nums[left];
            left++;
        }
        right++;
    }

    return minLength == Integer.MAX_VALUE ? 0 : minLength;
}