python leetcode 209 长度最小的子数组【中等题】

一 读懂题目

 

二. 分析,推导解法,产生思路。

解题思路:

1. 滑动窗口:

当右指针找到满足条件的连续子数组后,才开始移动左指针,直到未出现满足条件的连续子数组,再移动右指针。

时间复杂度:O(n)。左右指针最多各移动 n 次。 

空间复杂度:O(1)。

2. 前缀和+二分查找

前求数组的前缀和;再遍历数组,用二分查找,寻找i的最小连续子数组。

三 代码实现

1 滑动窗口

    def minSubArrayLen2(self, target, nums):
        # 滑动窗口
        right = 0
        left = 0
        temp_sum = 0
        nums_len = len(nums)
        min_len = nums_len+1
        while right < nums_len:
            temp_sum += nums[right]
            print(left, right, temp_sum, min_len)
            # 当右指针找到满足条件的连续子数组后,移动左指针,直到未出现满足条件的连续子数组,再移动右指针
            while temp_sum >= target :
                # 判断是否为长度最小的连续子数组
                min_len = min(min_len, right-left+1)
                temp_sum -= nums[left]
                left += 1
            right += 1

        return 0 if min_len == nums_len+1 else min_len

2 前缀和+二分查找

    def minSubArrayLen3(self, target, nums):
        # 前缀和+二分查找
        # 求前缀和
        nums_len =len(nums)
        sums =[0]   # python里list就相当于数组
        for i in range(nums_len):  # sum[i]表示:nums[0]到nums[i-1]之和
            sums.append(sums[i]+nums[i])
            # print(i,nums[i],sums)
        # 遍历数组,寻找i的连续子数组
        min_len = nums_len+1
        for i in range(nums_len):
            search_num = target + sums[i]
            # print(i,search_num)
            bound = Solution.BinarySearchBound(self,search_num,sums)
            if bound != -1: # 如果找到了,nums[i]的最小连续子数组
                min_len =min(min_len,bound-i)
        if min_len == nums_len +1:
            return 0
        return min_len

    def BinarySearchBound(self,target,nums):
        # 二分查找大于等于某个数的第一个位置
        l = 0
        r = len(nums)
        # 搜索区间: [left,right) whlie条件: l<r r初始值:len(nums)
        while l < r:
            mid = (l+r)//2
            # 若未找到大于等于的数值,则继续二分查找
            if target > nums[mid]:
                l = mid+1
            else:
                r = mid
        # 当循环结束后,l=r; 如果找到,nums[l]将是大于或等于target的第一个数
        if l != len(nums):
            return l
        return -1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值