【算法-LeetCode】209. 长度最小的子数组(滑动窗口)

209. 长度最小的子数组 - 力扣(LeetCode)

发布:2021年9月4日11:04:45

问题描述及示例

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-size-subarray-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

我的题解

记得上一次也做过一个有关滑动窗口的题目:

参考:【算法-LeetCode】3. 无重复字符的最长子串(滑动窗口)_赖念安的博客-CSDN博客

本题也可以借用这道题的思路。

我的题解1(滑动窗口)

总体思路是用一个辅助数组 minSubArray 来充当滑动窗口,并让一个全局变量 minLength 来存储目前 minSubArray 数组长度的历史最小值(注意 minLength 不是存储 minLength 的当前长度),同时将其值初始化为 Infinity 。在遍历 nums 的同时,往 minSubArray 中压入当前遍历的数组元素 nums[i]。每压入一个元素就判断 minSubArray 中的各元素和是否大于等于 target。如果满足这个条件,则将 minLength 的当前值与 minLength 的当前长度做比较并取其中的较小值作为 minLength 的新值;同时把 minLength 中的第一个元素弹出,重复上面那个判断。这样就能保证遍历完成后,minLength中保存的值就是满足题目条件的最小值。

为了方便表达,我还封装一个辅助函数 getArraySum(arr) 用于计算传入的 arr 数组中的元素之和。

/**
 * @param {number} target
 * @param {number[]} nums
 * @return {number}
 */
var minSubArrayLen = function (target, nums) {
  // 辅助数组 `minSubArray` 来充当滑动窗口
  let minSubArray = [];
  // `minLength` 用来存储目前 `minSubArray` 数组长度的历史最小值
  // 初始化为 Inifity 是为了防止后面在 Math.min() 中做大小判断时有个初始参照
  // 其实初始化为nums.length + 1 也可以,因为minLength 最大也就取nums.length
  let minLength = Infinity;
  // 开始遍历 nums 数组
  for (let i = 0; i < nums.length; i++) {
	// 在遍历nums的同时,往minSubArray中压入当前遍历的数组元素nums[i]
    minSubArray.push(nums[i]);
    // 如果minSubArray中的各元素和大于等于target
    while (getArraySum(minSubArray) >= target) {
      // 则更新minLength的值,
      minLength = Math.min(minLength, minSubArray.length);
      // 并把minSubArray的第一个元素弹出
      minSubArray.shift();
    }
  }
  // 如果遍历完nums之后,minLength的值仍为Infinity,说明nums中的所有元素
  // 相加之和都比target小,此时按题意就应返回0,否则直接返回minLength
  return minLength === Infinity ? 0 : minLength;
  
  // getArraySum 用于计算传入的arr数组中的元素之和
  function getArraySum(arr) {
    let sum = 0;
    for (let i = 0; i < arr.length; i++) {
      sum += arr[i];
    }
    return sum;
  }
};


提交记录
19 / 19 个通过测试用例
状态:通过
执行用时:228 ms, 在所有 JavaScript 提交中击败了12.66%的用户
内存消耗:40.5 MB, 在所有 JavaScript 提交中击败了7.15%的用户
时间:2021/09/05 19:56	

可以看到这种解法的时间表现和空间表现不不怎么好,但是目前我还没想到要怎么优化。

我的题解2(暴力解法)

因为有了之前做的那道滑动窗口的经验,所以我一开始没有尝试去用暴力解法,但是仔细想想的话还是有暴力解法的。那就是穷举每一种连续子数组并计算出其元素和。同样用一个变量来记录这些子数组的历史最小值,遍历完之后将记录的结果返回即可。暴力解法估计性能表现也不怎么样,就不写了。

官方题解

更新:2021年7月29日18:43:21

因为我考虑到著作权归属问题,所以【官方题解】部分我不再粘贴具体的代码了,可到下方的链接中查看。

更新:2021年9月5日20:01:44

参考:长度最小的子数组 - 长度最小的子数组 - 力扣(LeetCode)

【更新结束】

有关参考

更新:2021年9月5日20:17:49
参考:【算法-LeetCode】3. 无重复字符的最长子串(滑动窗口)_赖念安的博客-CSDN博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值