代码随想录-数组-长度最小的子数组

62 阅读3分钟

给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。

示例:

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

提示:

  • 1 <= target <= 10^9
  • 1 <= nums.length <= 10^5
  • 1 <= nums[i] <= 10^5

思路

暴力解法(运行时间超时)

使用双层for循环,获取所有可能的子数组,取符合条件的子数组中的最小长度

function minSubArrayLen(target: number, nums: number[]): number {

  let len: number = nums.length

  // 初始化子数组长度len+1,查找到符合条件的任意子数组的长度都会比初始值小

  let n: number = len + 1

  let sum: number = 0

  // 双层for循环,遍历获取所有可能的子数组组合

  for (let i = 0; i < len; i++) {

    // 每次修改子数组起始位置的遍历时,都将子数组初始化和置0

    sum = 0

    // 修改子数组结束位置,子数组长度依次递增

    for (let j = i; j < len; j++) {

      // 更新子数组的和

      sum += nums[j]

      // 比较子数组和与目标值

      if (sum >= target) {

        // 判断当前符合条件的子数组的长度是否是最小的

        n = j - i + 1 <= n ? j - i + 1 : n

        break

      }

    }

  }

  // 若长度值还为初始值,表示暂无满足条件的子数组,返回0

  return n > len ? 0 : n

};

滑动窗口

滑动窗口就是不断的调整子序列的开始位置和结束位置,从而得到我们想要的结果。

暴力解法通过两个for循环嵌套去改变子数组的初始和结束位置,而滑动窗口通过for循环改变子数组的结束位置,当子数组元素之和符合条件时,获取其长度,此时移动子数组的初始位置,直至子数组长度小于目标值,则继续移动子数组结束位置,从而获取到满足条件的子数组的最小长度。

209.长度最小的子数组.gif

function minSubArrayLen(target: number, nums: number[]): number {

  // 起始指针

  let left: number = 0,

  // 返回值初始化为最大值

    res: number = Infinity,

    // 符合条件的子数组长度

    subLen: number = 0,

    // 子数组的和

    sum: number = 0

  // 遍历终止位置指针

  for (let right: number = 0; right < nums.length; right++) {

    sum += nums[right]

    // 当子数组符合条件时

    while (sum >= target) {

      // 获取符合条件的最小子数组长度

      subLen = right - left + 1

      res = Math.min(res, subLen)

      // 子数组初始指针右移,子数组长度减一,子数组和更新,若子数组和不符合条件,则子数组终止位置指针右移

      sum -= nums[left]

      left++

    }

  }

  // 若返回值还为最大值,表示没有符合条件的子数组,返回0

  return res === Infinity ? 0 : res

}

滑动窗口的精妙之处在于根据当前子序列和大小的情况,不断调节子序列的起始位置。从而将O(n^2)暴力解法降为O(n)。

  • 时间复杂度:O(n),其中 n 是数组的长度。指针 start 和 end 最多各移动 n 次。
  • 空间复杂度:O(1)。

for里放一个while的时间复杂度不一定是O(n^2), 主要是看每一个元素被操作的次数,每个元素在滑动窗后进来操作一次,出去操作一次,每个元素都是被操作两次,所以时间复杂度是 2 × n 也就是O(n)