题目:长度最小的子数组
给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组。如果不存在符合条件的连续子数组,返回 0。
示例:
输入: s = 7, nums = [2,3,1,2,4,3],输出: 2
解释: 子数组 [4,3] 是该条件下的长度最小的连续子数组。
进阶:
如果你已经完成了O(n) 时间复杂度的解法, 请尝试 O(n log n) 时间复杂度的解法。
------------------------------------------------------------------
解法1:最容易想到的方法,直接遍历所有可能的组合。时间复杂度:O(n^2)
class Solution(object):
def minSubArrayLen(self, s, nums):
"""
:type s: int
:type nums: List[int]
:rtype: int
"""
if not nums:
return 0
li = []
for i in range(len(nums)-1):
for j in range(i+1, len(nums)+1):
# print(nums[i:j])
if sum(nums[i:j]) >= s:
li.append(len(nums[i:j]))
# print(li)
if len(li) == 0:
return 0
else:
return min(li)
解法2:使用python自带的 enumerate() 方法来遍历。时间复杂度:O(n^2)
enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。
语法:enumerate(sequence, [start=0])
参数:sequence -- 一个序列、迭代器或其他支持迭代对象。
start -- 下标起始位置。
class Solution(object):
def minSubArrayLen(self, s, nums):
"""
:type s: int
:type nums: List[int]
:rtype: int
"""
if not nums:
return 0
minLen = len(nums)+1
for i, _ in enumerate(nums):
total= 0
for j, tmp in enumerate(nums[i:]):
total += tmp
if total >= s:
minLen = min(minLen, j+1)
# 如果没有发生任何替换, 说明不存在
if minLen == len(nums)+1:
return 0
return minLen
解法3: 双指针,或对撞指针。不断判断跟s的大小,如果大了,说明元素太多,左移;反之小了,右移。时间复杂度:O(n)
class Solution(object):
def minSubArrayLen(self, s, nums):
"""
:type s: int
:type nums: List[int]
:rtype: int
"""
if not nums:
return 0
# 创建2个指针
pointer1, pointer2 = 0, 0
total = 0
nums_len = len(nums)
minL = nums_len + 1
while pointer1 < nums_len:
if pointer2 < nums_len and total < s:
total += nums[pointer2]
pointer2 += 1
else:
total -= nums[pointer1]
pointer1 += 1
if total >= s:
minL = min(minL, pointer2-pointer1)
if minL == nums_len + 1:
return 0
return minL
解法4:因为涉及到 "连续子数组",一旦提到连续二字,我们想到可以通过 二分法 来简化处理。时间复杂度:O(nlog(n))。
class Solution(object):
def sumJudge(self, nums, index, s):
sum = 0
for i, _ in enumerate(nums):
if i >= index:
sum -= nums[i-index]
sum += nums[i]
if sum >= s:
return True
return False
def minSubArrayLen(self, s, nums):
"""
:type s: int
:type nums: List[int]
:rtype: int
"""
if not nums:
return 0
left = 1
right = len(nums)
result = 0
while left <= right:
mid = left + (right - left)//2
if self.sumJudge(nums, mid, s):
right = mid - 1
result = mid
else:
left = mid + 1
return result
解法5:动态规划法,不需要每次循环都计算加和。时间复杂度:O(nlog(n))。
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
low, high = 0, -1
subsum = 0
while (low < len(nums)):
#
if (subsum < s) and (high+1 < len(nums)):
high += 1
subsum += nums[high]
else:
subsum -= nums[low]
low += 1
if subsum >= s:
res = min(res, high - low + 1)
return res if res != len(nums) + 1 else 0
参考:
https://www.runoob.com/python/python-func-enumerate.html