给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组。如果不存在符合条件的连续子数组,返回 0。
示例:
输入:s = 7, nums = [2,3,1,2,4,3]
输出: 2 解释: 子数组[4,3]
是该条件下的长度最小的连续子数组。
进阶:
如果你已经完成了O(n) 时间复杂度的解法, 请尝试 O(n log n) 时间复杂度的解法。
思路:
sliding window, 用双指针lo, hi 维护区间,如果区间和小于 s, 说明还需要更多的元素,则hi 往右移,
如果区间和大于s, 说明可以尝试减少元素来得到最短的满足条件的区间,则lo往右移。
class Solution(object):
def minSubArrayLen(self, s, nums):
"""
:type s: int
:type nums: List[int]
:rtype: int
"""
if not nums:
return 0
res = 2 << 31
lo, hi = 0, 0
while(hi < len(nums) and lo <= hi):
if sum(nums[lo:hi + 1]) < s:
hi += 1
elif sum(nums[lo:hi + 1]) >= s:
res = min(res, hi - lo + 1)
lo += 1
# print nums[lo: hi + 1]
return res if res != 2 << 31 else 0
下面的是利用动态规划思想修改后写法,会快很多。
主要修改点在于不用每一次循环都计算整个区间的和,
而是只需要根据移动方向来执行一次加或减运算来得到新的subsum
class Solution(object):
def minSubArrayLen(self, s, nums):
"""
:type s: int
:type nums: List[int]
:rtype: int
"""
if not nums:
return 0
res = len(nums) + 1
lo, hi = 0, -1
subsum = 0
while(lo < len(nums)):
if subsum < s and hi + 1 < len(nums):
hi += 1
subsum += nums[hi]
else:
subsum -= nums[lo]
lo += 1
if subsum >= s:
res = min(res, hi - lo + 1)
return res if res != len(nums) + 1 else 0
下面的写于2019年7月24日19:03:32:
class Solution(object):
def minSubArrayLen(self, s, nums):
"""
:type s: int
:type nums: List[int]
:rtype: int
"""
if not nums:
return 0
left, right = 0, 0
interval_sum = nums[0]
res = 1 << 31
while right < len(nums) and left <= right:
# print nums[left:right + 1], interval_sum, left, right
if interval_sum < s:
right += 1 #需要更多的数,向右拓展
if right < len(nums):
interval_sum += nums[right]
else:
res = min(res, right - left + 1)
interval_sum -= nums[left]
left += 1 #满足条件,试着缩小区间
# res = min(res, right - left + 1)
return res if res != 1 <<31 else 0