LeetCode探索(102):209-长度最小的子数组

118 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第30天,点击查看活动详情

题目

给定一个含有 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 <= 10^9
  • 1 <= nums.length <= 10^5
  • 1 <= nums[i] <= 10^5

进阶:

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

思考

本题难度中等。

首先是读懂题意。我们需要找出含有 n 个正整数的数组中满足其和 ≥ target 的长度最小的连续子数组,并返回其长度。

我们可以使用滑动窗口的方法。定义两个指针 start 和 end 分别表示子数组(滑动窗口)的开始位置和结束位置,维护变量 sum 存储子数组中的元素和(即从索引 start 到 end 的元素和)。我们每次对指针end右移一位,sum加上nums[end]的数值,并判断sum是否满足 ≥ target。若满足,则更新子数组的长度,并将左指针start右移一位,继续进行判断。

考虑到指针 start 和 end 最多各移动 n 次,因此时间复杂度是O(n),其中 n 是数组的长度。

解答

方法一:滑动窗口

/**
 * @param {number} s
 * @param {number[]} nums
 * @return {number}
 */
function minSubArrayLen(s, nums) {
  let n = nums.length
  if (n == 0) {
    return 0
  }
  let ans = Number.MAX_VALUE
  let start = 0, end = 0
  let sum = 0
  while (end < n) {
    sum += nums[end]
    while (sum >= s) {
      ans = Math.min(ans, end - start + 1)
      // start右移一位
      sum -= nums[start]
      start++
    }
    // end右移一位
    end++
  }
  return ans == Number.MAX_VALUE ? 0 : ans
}

复杂度分析:

  • 时间复杂度:O(n),其中 n 为数组的长度。
  • 空间复杂度:O(1)。

参考