原题如下:
1、双指针法(56ms,15.2mb)
因为要求连续区间,可以采用前后指针,t表示前后指针区间内的数字之和。
流程
1、当t<s,end+=1;
2、当t>=s,begin+=1
终止条件为end<l。
每个元素最多遍历两次,即前指针一次,后指针一次,因此时间复杂度O(n),空间复杂度O(1)。
代码:
class Solution:
def minSubArrayLen(self, s: int, nums: List[int]) -> int:
if nums==[]:
return 0
l=len(nums)
begin,end=0,0
ret,t=float("inf"),nums[0]
while end<l:
if t>=s:
ret=min(ret,end-begin+1)
if begin<end:
t-=nums[begin]
begin+=1
else:
break
else:
if end<l-1:
end+=1
t+=nums[end]
else:
break
return ret if ret<float("inf") else 0
2、二分查找(152ms,15.3mb)
这个题比较奇怪,O(n)复杂度好想而且快,进阶却要求O(nlogn)的解法。
笔者二分查找的思路相对复杂,这里就不介绍了,直接看大神思路(原文链接):
1、nums转换为前缀和数组,例如[1,2,3,4]转化为[1,3,6,10]。此时为递增序列,可以使用二分。
2、遍历前缀和数组,对于当前数字下标i:
(1)如果nums[i]<s,continue;
(2)nums[i]>=s,向前二分查找j,当找到最后一个j满足nums[i]-nums[j]>=s,ret=min(ret,i-j)。
笔者手写的代码:
class Solution:
def minSubArrayLen(self, s: int, nums: List[int]) -> int:
for index in range(1,len(nums)):
nums[index]+=nums[index-1]
ret=float("inf")
for index in range(len(nums)):
if nums[index]<s:
continue
begin,end=0,index
ret=min(ret,index+1)
while begin<=end:
mid=(begin+end)//2
if nums[index]-nums[mid]>=s:
ret=min(ret,index-mid)
begin=mid+1
else:
end=mid-1
return ret if ret<float("inf") else 0