(leetcode 209)长度最小的子数组(双指针法、二分查找)

原题如下:
在这里插入图片描述

1、双指针法(56ms,15.2mb)

因为要求连续区间,可以采用前后指针,t表示前后指针区间内的数字之和。
流程
1、当t<s,end+=1;
2、当t>=s,begin+=1
终止条件为end<l。

每个元素最多遍历两次,即前指针一次,后指针一次,因此时间复杂度O(n),空间复杂度O(1)。
代码:

class Solution:
    def minSubArrayLen(self, s: int, nums: List[int]) -> int:
        if nums==[]:
            return 0
        l=len(nums)
        begin,end=0,0
        ret,t=float("inf"),nums[0]
        while end<l:
            if t>=s:
                ret=min(ret,end-begin+1)
                if begin<end:
                    t-=nums[begin]
                    begin+=1
                else:
                    break
            else:
                if end<l-1:
                    end+=1
                    t+=nums[end]
                else:
                    break
        return ret if ret<float("inf") else 0
            

2、二分查找(152ms,15.3mb)

这个题比较奇怪,O(n)复杂度好想而且快,进阶却要求O(nlogn)的解法。
笔者二分查找的思路相对复杂,这里就不介绍了,直接看大神思路(原文链接):
1、nums转换为前缀和数组,例如[1,2,3,4]转化为[1,3,6,10]。此时为递增序列,可以使用二分。
2、遍历前缀和数组,对于当前数字下标i:
(1)如果nums[i]<s,continue;
(2)nums[i]>=s,向前二分查找j,当找到最后一个j满足nums[i]-nums[j]>=s,ret=min(ret,i-j)。

笔者手写的代码:

class Solution:
    def minSubArrayLen(self, s: int, nums: List[int]) -> int:
        for index in range(1,len(nums)):
            nums[index]+=nums[index-1]
        ret=float("inf")
        for index in range(len(nums)):
            if nums[index]<s:
                continue
            begin,end=0,index
            ret=min(ret,index+1)
            while begin<=end:
                mid=(begin+end)//2
                if nums[index]-nums[mid]>=s:
                    ret=min(ret,index-mid)
                    begin=mid+1
                else:
                    end=mid-1
        return ret if ret<float("inf") else 0
            

猜你喜欢

转载自blog.csdn.net/qq_41584385/article/details/106292028