算法题解-长度最小的子数组

208 阅读2分钟

题目

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

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

题解

第一种

我们这里先采用暴力枚举进行实现,首先我们在函数中接受两个参数,一个数字s和一个数组nums,在函数使用两个指针i和j分别表示子数组的起始位置和终止位置,默认值我们先设为0,在函数使用一个变量minl来记录当前找到的最小子数组的长度,初始值为数组nums的长度加1,在函数中我们使用一个while循环来遍历数组nums,在循环中,我们首先计算从i开始的连续j个元素的和total,如果total大于等于s,我们则更新minl的值为min,如果total小于s,我们则继续向右移动j,直到total大于等于s或者j超出数组范围为止,如果minl的值没有被更新,则说明找不到符合条件的子数组,最后我们将minl变量返回出去即可

var minSubArrayLen = function (s, nums) {
  let minl = nums.length + 1
  for (let i = 0; i < nums.length; i++) {
    let total = nums[i]
    let j = 1
    while (total < s && i + j < nums.length) {
      total += nums[i + j]
      ++j
    }
    if (total >= s) {
      minl = Math.min(minl, j)
    }
  }
  if (minl === nums.length + 1) {
    minl = 0
  }
  return minl
}

第二种

我们这里还可以采用双指针方式进行实现,我们在函数中先使用两个指针start和end分别代表子数组的起始位置和终止位置,初始值我们先设为0,函数中我们使用一个变量sum来记录当前子数组的元素之和,值为0,使用一个变量minLen来记录当前找到的最小子数组的长度,初始值为正无穷,接下来我们在函数中使用while循环进行遍历数组nums,循环中我们首先计算从start到end的元素之和sum,如果sum小于s,我们则将end右移一位,继续向右扩展子数组,如果sum大于等于s,我们则更新minLen的值为min,然后我们将start右移一位并将sum减去移除的第一个元素和移动后的第一个元素,这样就得到了一个新的子数组,继续判断其元素之和是否大于等于s,最后如果minLen的值没有被更新,则说明找不到符合条件的子数组返回0否则返回minLen即可

var minSubArrayLen = function (s, nums) {
  let start = 0
  let end = 0
  let sum = 0
  let minLen = +Infinity
  while (end < nums.length) {
    sum = sum + nums[end]
    if (sum < s) {
      end++
    } else {
      minLen = Math.min(minLen, end - start + 1)
      sum = sum - nums[start] - nums[end]
      start++
    }
  }
  return minLen == +Infinity ? 0 : minLen
}

坚持努力,无惧未来!