leetcode的python实现-(209) 长度最小的子数组
题目描述
给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组,并返回其长度。如果不存在符合条件的连续子数组,返回 0。
示例:
输入: s = 7, nums = [2,3,1,2,4,3]
输出: 2
解释: 子数组 [4,3] 是该条件下的长度最小的连续子数组。
思路
1.双指针
使用两个指针l和r, 指针r先往后扫描,得到前缀和第一次大于目标值s时,指针l 再从头开始扫描,每次l 的起始位置和r 的结束位置构成一个窗口,在这个窗口中找到长度最小的连续子数组的长度.时间复杂度O(n),空间复杂度为O(1)。
2.一次遍历+二分查找
使用前缀和的额外数组sums,若sums[j] - sum[i] = s,则连续子数组的长度为j-i+1,需要找到最小的j-i+1,其中一次遍历确定索引i,二分查找确定索引j,时间复杂度为O(nlogn),空间复杂度为O(n)。
python3实现
1.双指针.
class Solution:
def minSubArrayLen(self, s: int, nums: List[int]) -> int:
if not nums:
return 0
n = len(nums)
ans = n + 1
l, r = 0, 0
nsum = 0
while r < n:#
nsum += nums[r]
while nsum >= s:
ans = min(ans, r - l + 1)
nsum -= nums[l]
l += 1
r += 1
return ans if ans != n + 1 else 0
2.一次遍历+二分查找.
class Solution:
def minSubArrayLen(self, s: int, nums: List[int]) -> int:
if not nums:
return 0
n = len(nums)
ans = n + 1
sums = [0]
for i in range(n):
sums.append(sums[-1] + nums[i])#前缀和序列,升序
print(sums)
for i in range(1, n + 1):
target = s + sums[i - 1]
bound = self.binarySearchIndex(sums, target)
if bound != len(sums):
ans = min(ans, bound - (i - 1))#取最小的长度
return 0 if ans == n + 1 else ans
#二分法,返回查找值或第一个大于它的索引
def binarySearchIndex(self, nums, target):
l , r = 0, len(nums)
while l< r:
mid = (l+r)//2
if nums[mid] == target:
return mid
elif nums[mid] < target:
l = mid+1
else:
r = mid
return l
参考:
[1] https://leetcode-cn.com/problems/minimum-size-subarray-sum/solution/chang-du-zui-xiao-de-zi-shu-zu-by-leetcode-solutio/
[2] https://leetcode-cn.com/problems/minimum-size-subarray-sum/
欢迎关注公众号-算法学习总结,获取更多题解,欢迎共同交流学习