剑指 Offer II 008. 和大于等于 target 的最短子数组(滑动窗口模块)

163 阅读1分钟

每日刷题第5天 2021.12.30

和大于等于 target 的最短子数组

  • 难度:中等
  • 方法:滑动窗口

题目

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

示例

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

解法

  • 定义两个指针startend 分别表示子数组(滑动窗口窗口)的开始位置和结束位置,维护变量 ans 存储子数组中的元素和(即从 nums[start]nums[end] 的元素和)。

  • 初始状态下,startend 都指向下标 0ans 的值为 0

  • 每一轮迭代,将 nums[end] 加到ans,如果ans ≥ target,则更新子数组的最小长度(此时子数组的长度是end − start + 1),然后将 nums[start]ans 中减去并将 start 右移,直到 ans < target,在此过程中同样更新子数组的最小长度。在每一轮迭代的最后,将 end 右移。

/**
 * @param {number} target
 * @param {number[]} nums
 * @return {number}
 */
var minSubArrayLen = function(target, nums) {
  let ans = 0;
  nums.forEach(ele => ans += ele);
  // 处理两种特殊情况
  if (ans < target) {
    return 0;
  }
  if (ans == target) {
    return nums.length;
  }
  // 当ans大于target的情况
  let start = 0;
  let end = 0;
  ans = 0;
  let minLen = Infinity;
  let len = 1;
  // 标志位
  let flag = false;
  while (start >= 0 && start < nums.length && end >= 0 && end < nums.length) {
    if(!flag){
      ans += nums[end];
    }
    if (ans < target) {
      flag = false;
      end++;
    }else {
      flag = true;
      // 记录下当前符合的长度
      len = end - start + 1;
      // 取得当前最小的长度
      minLen = Math.min(minLen,len);
      if (start == end) {
        end++;
      }
      ans -= nums[start];
      start++;
    }
  }
  return minLen;
};
  • 简洁的解法
/**
 * @param {number} target
 * @param {number[]} nums
 * @return {number}
 */
var minSubArrayLen = function(target, nums) {
  let ans = 0;
  // 处理两种特殊情况
  if (ans < target) {
    return 0;
  }
// 使用滑动窗口算法
ans = 0;
let start = 0;
let end = 0;
let n = nums.length;
let minLen = Infinity;
while (end < n){
  ans += nums[end];
  while(ans >= target) {
    minLen = Math.min(minLen, end - start + 1);
    ans -= nums[start];
    start++;
  }
  end++;
}
return minLen;
};

附录

  • 双指针思想