长度最小的子数组
力扣209
首先尝试:暴力解法,两个for循环,一个控制区间左端点,一个控制区间右端点,不断寻找符合条件的子序列,找到一个就更新res和左端点:
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
res = float('inf') #定义无限大的数
n = len(nums)
for i in range(n):
sum = 0
for j in range(i, n): #从i开始向后计算
sum += nums[j]
if sum >= target: #找到符合目标的序列,更新res
res = min(res, j - i + 1)
break #要找最短的,符合条件后面的就不用看了
return 0 if res == float('inf') else res
时间复杂度:O(n^2);空间复杂度:O(1)。力扣不能通过,显示超时。
优化方法:滑动窗口(类似双指针)。
所谓滑动窗口,就是不断调节子序列的起始位置和终止位置,从而得出我们想要的结果。在暴力解法中,是一个for循环调节滑动窗口的起始位置,一个for循环调节滑动窗口的终止位置,用两个for循环完成了一个不断搜索区间的过程。而滑动窗口是用一个for循环来完成这个操作。重点:
- 窗口内满足的条件?1其和 ≥ target;2长度最小;3连续。
- 这个for循环控制的是起始位置还是终止位置?假设是起始位置,那么终止位置的操作与暴力解法无异,所以应该是终止位置。
- 起始位置如何移动?如果当前窗口的值大于target了,起始位置向后移动,找到满足条件的长度最小的窗口,更新res。
- while sum >= target: 用while而不是if,因为可能最后一个数值比较大,起始位置不止移动一次。