题目

给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组,并返回其长度。如果不存在符合条件的连续子数组,返回 0

image.png

思路

1. 暴力法

枚举nums中每个数num,索引为i。再枚举索引[i, len(nums)]满足条件的最小长度。
两层循环,最大时间复杂度【LeetCode】209. 长度最小的子数组 - 图2

2. 前缀和 + 二分查找

因为数组中所有元素都是整数,所以前缀和一定是递增的。
image.png

  1. sums = [0]
  2. for i in range(n):
  3. sums.append(sums[-1] + nums[i])

二分查找用于查找到当前索引的
重点:sums(bound) - sum(i - 1) >= s

最大时间复杂度:O(nlogn)

3. 双指针法

image.png
其实就是滑动窗口法。
时间复杂度:O(n)O(n),其中 nn 是数组的长度。指针 left 和 right 最多各移动 nn 次。

代码

滑动窗口

  1. class Solution:
  2. def minSubArrayLen(self, s: int, nums: List[int]) -> int:
  3. # 滑动窗口
  4. def isBiggerNum(nums, num):
  5. return sum(nums) >= num
  6. left, right = 0, 0
  7. min_len = float('INF')
  8. while right <= len(nums):
  9. right += 1
  10. while isBiggerNum(nums[left:right], s):
  11. # print(left, right)
  12. min_len = min(min_len, right - left)
  13. left += 1
  14. return min_len if min_len != float('INF') else 0

前缀和+二分查找

  1. class Solution:
  2. def minSubArrayLen(self, s: int, nums: List[int]) -> int:
  3. if not nums:
  4. return 0
  5. n = len(nums)
  6. ans = n + 1
  7. sums = [0]
  8. for i in range(n):
  9. sums.append(sums[-1] + nums[i])
  10. for i in range(1, n + 1):
  11. target = s + sums[i - 1]
  12. bound = bisect.bisect_left(sums, target)
  13. if bound != len(sums):
  14. ans = min(ans, bound - (i - 1))
  15. return 0 if ans == n + 1 else ans

官方写的代码,比我要优化很多,在于保存前面已经加过的值

  1. class Solution:
  2. def minSubArrayLen(self, s: int, nums: List[int]) -> int:
  3. if not nums:
  4. return 0
  5. n = len(nums)
  6. ans = n + 1
  7. start, end = 0, 0
  8. total = 0
  9. while end < n:
  10. total += nums[end]
  11. while total >= s:
  12. ans = min(ans, end - start + 1)
  13. total -= nums[start]
  14. start += 1
  15. end += 1
  16. return 0 if ans == n + 1 else ans
  17. 作者:LeetCode-Solution
  18. 链接:https://leetcode-cn.com/problems/minimum-size-subarray-sum/solution/chang-du-zui-xiao-de-zi-shu-zu-by-leetcode-solutio/
  19. 来源:力扣(LeetCode
  20. 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

暴力法

  1. class Solution:
  2. def minSubArrayLen(self, s: int, nums: List[int]) -> int:
  3. if not nums:
  4. return 0
  5. n = len(nums)
  6. ans = n + 1
  7. for i in range(n):
  8. total = 0
  9. for j in range(i, n):
  10. total += nums[j]
  11. if total >= s:
  12. ans = min(ans, j - i + 1)
  13. break
  14. return 0 if ans == n + 1 else ans
  15. 作者:LeetCode-Solution
  16. 链接:https://leetcode-cn.com/problems/minimum-size-subarray-sum/solution/chang-du-zui-xiao-de-zi-shu-zu-by-leetcode-solutio/
  17. 来源:力扣(LeetCode
  18. 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。