题目描述
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [ n u m s i nums_i numsi, n u m s i + 1 nums_{i+1} numsi+1, …, n u m s r − 1 nums_{r-1} numsr−1, n u m s r nums_r 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
思路分析
题意给定一个无需的容量为n的正整数数组和一个正整数target,要我们找出和大于等于target的最短子数组。因为是无序的,而且我们要找的是连续的子数组,那么会比较自然的想到滑动窗口的方法。设定窗口的起点 left 和终点 right,逐步从数组左端滑动至右端,期间根据窗口覆盖子数组的和进行窗口大小的调整。假设此时窗口内的子数组和大于等于target,那么一直去除窗口起点的元素直到窗口内的元素和小于target,然后继续扩展窗口的终点,如此循环,直到窗口终点移动到数组最右端。
这么说可能比较抽象,大家看一下代码估计就能明白了。
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
if sum(nums) < target:
return 0
ans = len(nums) #最终返回的结果
res = 0 #滑动窗口覆盖子数组的和
#题意要求找到和>=target的最短连续子数组
#首先想到使用滑动窗口的方法解决问题
l, r = 0, 0 #定义窗口的起点和终点
while r < len(nums):
#窗口终点向右滑动
res += nums[r]
#如果窗口覆盖子数组的值>=target, 调整窗口起点的位置
while res >= target:
ans = min(ans, r - l + 1)
res -= nums[l]
l += 1
#窗口起点调整好之后,继续向前移动
r += 1
return ans
程序运行结果
可以看到,代码的效率还是很高的。
总结
做过一部分数组的题之后,发现数组的题目大多可以用二分查找、双指针、动态规划等方法解决,根据具体题目选择具体的方法即可,要学会从题意中抽象出数学模型,再做决策。