leetcode的python实现-(209) 长度最小的子数组

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/

欢迎关注公众号-算法学习总结,获取更多题解,欢迎共同交流学习
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值