参考文献 代码随想录
一、长度最小的子数组
给定一个含有 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
进阶:
- 如果你已经实现
O(n)
时间复杂度的解法, 请尝试设计一个O(n log(n))
时间复杂度的解法。
暴力
class Solution(object): def minSubArrayLen(self, target, nums): """ :type target: int :type nums: List[int] :rtype: int """ # 暴力思路: 2层循环寻找和大于等于target的,然后并计算长度 # 定义一个临时变量result存放的是和大于等于target的最小长度 result = float('inf') for i in range(len(nums)): # 先从每一个元素开始找 tmpSum = 0 # 临时存放每个长度之和 for j in range(i, len(nums)): # 找这个元素后面的元素 tmpSum += nums[j] if tmpSum >= target: # 一旦找到,此时必定是当前最小的长度 result = min(result, j - i + 1) break # 调出循环 if result == float('inf'): return 0 return result
滑动窗口(双指针)
使用2个指针,一个慢指针(就是更新的值没有另外一个指针快),一个快指针(同理),还需要定义一个变量,接受对应长度的和,result变量统计最小长度之和大于等于target的,然后while循环,那么这个while循环的条件是什么呢?是快指针小于数组的长度,那为什么不判断慢指针呢?因为快指针比慢指针更快到达数组的长度,在while循环,统计和,然后判断此时的和是否大于等于target,问题来了?是使用if呢,还是while呢,这里举一个例子:假设target = 3,数组为[2,3,1,2,4,3],当统计到3,1,2,4的时候,此时是大于target的,那么当满足条件后,移动慢指针时,剩下的还是大于等于target,所以使用while判读,条件成立后,对应的长度=快-慢+1,然后先对和做减法,然后在移动,为什么?因为如果你先移动慢指针,那么在对和做减法的话,就会出错。
class Solution(object): def minSubArrayLen(self, target, nums): """ :type target: int :type nums: List[int] :rtype: int """ # 滑动窗口: 双指针寻找和大于等于target的,然后并计算长度, # 定义一个临时变量result存放的是和大于等于target的最小长度 result = float('inf') slow = 0 fast = 0 tmpSum = 0 # 记录临时对应长度的和 while fast < len(nums): tmpSum += nums[fast] while tmpSum >= target: # 为什么要使用while,因为当你移动慢指针的时候,结果还可能大于等于target result = min(result, fast - slow + 1) tmpSum -= nums[slow] # 把慢指针向