leetcode209. 长度最小的子数组

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

示例:

输入: s = 7, nums = [2,3,1,2,4,3]
输出: 2
解释: 子数组 [4,3] 是该条件下的长度最小的连续子数组。

方法:双指针滑窗

思路:

因为是子数组,本题可以想到的一种方法是使用双指针维护一个窗口,来求得窗口内的和,进而找到最短长度的子数组。

我刚开始想到的是,左右指针分别在nums开头和结尾,也就是说刚开始的窗口是整个数组,如果小于s,那么肯定不对,之后不断的缩小窗口,判断左右指针指向的元素,抛弃小的那个元素;但是如果左右指针指向的元素相同,那么不好判断,可能需要进一步判断两个指针内层的元素,才能找到丢弃哪一个对整个窗口的影响较小,代码不好写,计算量也大;而且刚开始求整个数组的和,已经O(N)了,算是额外的计算量。

正确的方法是这样的:刚开始两个指针都在开头位置,相当于开始维护的窗口是只有第一个元素的子数组,如果小于s,就right开始向右扩张,直到窗口内大于等于s,这时,更新ans长度,然后将左指针left开始向右缩,直到窗口和小于s,缩的同时也更新ans;小于了之后,继续重复上述过程,right向右扩张…left向右缩…直到遍历完数组。

最后返回ans即可,初始将ans设为无穷大,如果最后ans还是无穷大,说明没有符合条件的子数组,返回0。

最坏的情况左右指针都遍历了一遍,O(2N),渐进时间复杂度为O(N)。空间复杂度为O(1)。

代码:

class Solution:
    def minSubArrayLen(self, s: int, nums: List[int]) -> int:
        n = len(nums)
        if not n:
            return 0
        #ans为满足条件的最小长度
        ans = float('inf')
        #初始化左右指针,刚开始维护的窗口是nums的第一个元素
        left = right = 0
        #初始化temp,temp变量维护当前窗口的元素和
        temp = 0
        while right < n:
            temp += nums[right]
            #已经大于等于s的话,缩小窗口,更新ans
            while temp >= s:
                ans = min(ans,right-left+1)
                temp -= nums[left]
                left += 1
            #temp小于s的话,扩大窗口
            right += 1
        return ans if ans != float('inf') else 0

结果:

python 数组长度宽度 python数组长度最大_算法