【每日演算法】長度最小的子數組

題目描述


這是 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

分析題目要求

字元串或數組找到滿足條件的連續區間的問題可以想到的使用:滑動窗口的方法去解決。
在數組中使用滑動窗口的有出有進的,則需使用雙端隊列的方式可以在O(1)時間內完成。
定義一個隊列,記錄窗口內的元素,還需要一個變數記錄窗口內元素的總和,因為要計算窗口內元素和與target進行比較。

程式碼實現

import collections
class Solution(object):
    def minSubArrayLen(self, target, nums):
        q=collections.deque()#記錄窗口內的元素索引號
        t=0#窗口內的元素的總和
        res=float("inf")#記錄結果,默認最大值 
        for i,v in enumerate(nums):
            # print(i,v,q,t)
            q.append(i)
            t+=v
            while t>=target:#窗口內的元素和滿足條件,則從左側逐個移除,找到最小的
                res=min(res,q[-1]-q[0]+1)
                if res==1:
                    return res
                t-=nums[q.popleft()]#移除左側的元素
        # print(q,t)
        return 0 if res==float("inf") else res