【每日算法】长度最小的子数组

题目描述


这是 LeetCode 上的 209. 长度最小的子数组
难度为 【困难】

给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
示例 1:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
示例 2:
输入:target = 4, nums = [1,4,4]
输出:1
示例 3:
输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0
提示:
1 <= target <= 10^9
1 <= nums.length <= 10^5
1 <= nums[i] <= 10^5

暴力解法

首先最容易想到的是暴力求解,首先定义一个数组,用于记录'连续'元素累加的和,使用两层循环,
外层是参与运算的个数,连着1个数,连着2个数,连接3个数等等,内层是把连着的数累加,并找到最终的结果。
内层从后往前累加,因为后面的结果要用到前面计算的结果
nums=[2,3,1,2,4,3]为例

定义一个数组:sums=[0]*len(nums)
sums=[0,0,0,0,0,0]

当i=0时,表示有连着1个数字求和

j=5: sums[5]=sums[5]+nums[5]
j=4: sums[4]=sums[4]+nums[4]
...
j=0: sums[0]=sums[0]+nums[0]
sums=[2,3,1,2,4,3]

当i=1时,表示有连着2个数字求和,连着2个时,sums中只能计算到1

j=5: sums[5]=sums[5]+nums[4]
j=4: sums[4]=sums[4]+nums[3]
...
j=1: sums[1]=sums[1]+nums[0]
sums=[..,5,4,3,6,7]

当i=2时,表示有连着3个数字求和,连着3个时,sums中只能计算到2

j=5: sums[5]=sums[5]+nums[3]
j=4: sums[4]=sums[4]+nums[2]
...
j=2: sums[2]=sums[2]+nums[0]
sums=[..,...,6,5,10,9]

可以得出sums[j]=sums[j]+nums[j-i]

def minSubArrayLen(self, target, nums):
  n=len(nums)
  sums=[0]*n
  for i in range(n):
      for j in range(n-1,i-1,-1):
  	sums[j]=sums[j]+nums[j-i]
  	if sums[j]>=target:
  	    return i+1
  return 0

虽然暴力解法的能通过,但是速度着实很慢,有没有别的解法呢,我猜大概率是有的

双指针法

能不能用双指针法,左右两个指针,圈定满足条件的数据(其和 ≥ target)的数据范围,移动右边的指针,使其和越来越大,当>=target满足条件时,用左右指针索引计算个数,然后再向右移动左指针,使其值逐渐减小,如果还是满足>=targer的条件,用左右指针索引计算个数,然后向右再移动左指针,再判断target...,一直这样判断,直到右指针到尾。

def minSubArrayLen(self, target, nums):
  n=len(nums)
  lo,hi=0,0#左右指针
  tot,res=0,99999999#
  while hi<n:
      tot+=nums[hi]
      hi+=1#移动右边的指针
      #如果满足条件,则移动左指针,减小结果
      while tot>=target:
  	res=min(res,hi-lo)
  	tot-=nums[lo]
  	lo+=1
  return 0 if 99999999==res else res


结果很漂亮。

posted @ 2021-07-07 19:34  Hitechr  阅读(200)  评论(0)    收藏  举报