1、题目描述:
2、题解:
方法1:辅助队列
思路:
设置一个队列,把数组的首元素放进去,
然后遍历[1,n),n为数组的长度:
如果队列的元素之和小于s就继续往队列添加数组中的元素
循环处理队列的元素之和不小于s的情况:
选择满足条件的最短的连续子数组
把队列的首元素出队列
最后返回最小值(要判断res是否改变)
代码如下:
class Solution:
def minSubArrayLen(self, s: int, nums: List[int]) -> int:
#辅助队列
if not nums:
return 0
res = float('inf')
temp = [nums[0]]
n = len(nums)
for i in range(1,n):
if sum(temp) < s:
temp.append(nums[i])
while sum(temp) >= s:
res = min(res,len(temp))
temp.pop(0)
return res if res != float('inf') else 0
方法2:双指针法
辅助队列每次都要计算队列元素之和,浪费了时间,进行优化,考虑使用双指针法
其实大致思路是一样的,只不过我们不设置辅助队列,而是一个sum_,避免了重复计算队列的元素之和,能加快运算。
思路:
n = len(nums),为数组的长度
设置left,right两个指针,sum_是两个指针的之间的元素之和,res = float('inf')设置res为最大值
循环条件是right< n:
如果sum_<s:
让sum_加上right指针所指的元素
并且令right指针向右移动一次
循环处理sum_ >= s的情况:
先让sum_减去left指针所指的元素
保留res和right-left两者的最小值
令left指针向右移动一次
最后返回res,如果res的值不是一开始设置的最大值
如下图:上面一行是双指针法的结果,下面一行是辅助队列的结果,很容易就可以看到双指针法运行时间得到很大的优化
class Solution:
def minSubArrayLen(self, s: int, nums: List[int]) -> int:
#双指针法
if not nums:
return 0
n = len(nums)
left,right = 0,0
res = float('inf')
sum_ = 0
while right < n:
if sum_ < s:
sum_ += nums[right]
right += 1
while sum_ >= s:
sum_ -= nums[left]
res = min(res,right - left)
left += 1
return res if res != float('inf') else 0
方法3、二分查找:
题目说了用O(NlogN)的时间复杂度,想到了二分查找,然后需要有序。这时候需要定义一个有序数组。
有序数组sums[i],代表[0,i]的累计和。
然后去用二分查找法去做就行。
先写出暴力法的优化版本,但是python还是超时
class Solution:
def minSubArrayLen(self, s: int, nums: List[int]) -> int:
#优化暴力法,超时
if not nums:
return 0
n = len(nums)
sums = [0] * n
sums[0] = nums[0]
for i in range(1,n):
sums[i] = nums[i] + sums[i - 1]
res = float('inf')
for i in range(n):
s2 = s - nums[i] #除去当前数字
for j in range(i,n):
if sums[j] - sums[i] >= s2:
res = min(res,j - i + 1)
return res if res != float('inf') else 0
二分查找,也即是修改内层的for循环,对于sums[j] - sums[i] >= s2
,通过移项,也就是sums[j] >= s2 + sums[i]
,含义就是寻找一个sums[j]
,使得其刚好大于等于s2 + sums[i]
。因为sums是个有序数组,所有找sum[j]
可以采取二分的方法。
class Solution:
def minSubArrayLen(self, s: int, nums: List[int]) -> int:
#二分查找
if not nums:
return 0
n = len(nums)
sums = [0] * n
sums[0] = nums[0]
for i in range(1,n):
sums[i] = nums[i] + sums[i - 1]
res = float('inf')
for i in range(n):
s2 = s - nums[i] #除去当前数字
#二分查找,目标值是s2 + sums[i]
k = self.binarySearch(i,n-1,sums,s2 + sums[i])
if k != -1:
res = min(res,k - i + 1)
return res if res != float('inf') else 0
def binarySearch(self,start,end,sums,target):
while start <= end:
mid = start + (end - start) // 2
if sums[mid] == target:
return mid
elif sums[mid] < target:
start = mid + 1
else:
end = mid - 1
return mid if sums[mid] > target else -1
3、复杂度分析:
方法1:
时间复杂度:O(N^2),sum函数的复杂度是O(N)
空间复杂度:O(N)
方法2:
时间复杂度:O(N)
空间复杂度:O(1)
方法3:
时间复杂度:O(NlogN)
空间复杂度:O(N)