持续创作,加速成长!这是我参与「掘金日新计划 · 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^91 <= nums.length <= 10^51 <= 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)。