一 读懂题目
二. 分析,推导解法,产生思路。
解题思路:
1. 滑动窗口:
当右指针找到满足条件的连续子数组后,才开始移动左指针,直到未出现满足条件的连续子数组,再移动右指针。
时间复杂度:O(n)。左右指针最多各移动 n 次。
空间复杂度:O(1)。
2. 前缀和+二分查找
前求数组的前缀和;再遍历数组,用二分查找,寻找i的最小连续子数组。
三 代码实现
1 滑动窗口
def minSubArrayLen2(self, target, nums):
# 滑动窗口
right = 0
left = 0
temp_sum = 0
nums_len = len(nums)
min_len = nums_len+1
while right < nums_len:
temp_sum += nums[right]
print(left, right, temp_sum, min_len)
# 当右指针找到满足条件的连续子数组后,移动左指针,直到未出现满足条件的连续子数组,再移动右指针
while temp_sum >= target :
# 判断是否为长度最小的连续子数组
min_len = min(min_len, right-left+1)
temp_sum -= nums[left]
left += 1
right += 1
return 0 if min_len == nums_len+1 else min_len
2 前缀和+二分查找
def minSubArrayLen3(self, target, nums):
# 前缀和+二分查找
# 求前缀和
nums_len =len(nums)
sums =[0] # python里list就相当于数组
for i in range(nums_len): # sum[i]表示:nums[0]到nums[i-1]之和
sums.append(sums[i]+nums[i])
# print(i,nums[i],sums)
# 遍历数组,寻找i的连续子数组
min_len = nums_len+1
for i in range(nums_len):
search_num = target + sums[i]
# print(i,search_num)
bound = Solution.BinarySearchBound(self,search_num,sums)
if bound != -1: # 如果找到了,nums[i]的最小连续子数组
min_len =min(min_len,bound-i)
if min_len == nums_len +1:
return 0
return min_len
def BinarySearchBound(self,target,nums):
# 二分查找大于等于某个数的第一个位置
l = 0
r = len(nums)
# 搜索区间: [left,right) whlie条件: l<r r初始值:len(nums)
while l < r:
mid = (l+r)//2
# 若未找到大于等于的数值,则继续二分查找
if target > nums[mid]:
l = mid+1
else:
r = mid
# 当循环结束后,l=r; 如果找到,nums[l]将是大于或等于target的第一个数
if l != len(nums):
return l
return -1