0209-leetcode算法实现之长度最小子数组-minimum-size-subarray-sum-python&golang实现

给定一个含有 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 <= 109
1 <= nums.length <= 105
1 <= nums[i] <= 105

进阶:

如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-size-subarray-sum

python

# 长度最小的子数组
# 找出该数组中满足其和 ≥ target 的长度最小的 连续子数组[numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
class Solution:
    def minSubArrayLen(self, nums: [int], target: int) -> int:
        """
        滑动窗口,时间O(n), 空间O(1)
        思路:
        1.初始化求和sum,返回结果res,左边界index=0
        2.移动右边界,sum累加计和
        3.当sum < target,不断累加计和,重复步骤2
        4.当sum >= target,考虑移动左边界,减小sum值,res取上步res及序列长度i-index+1的较小值
        5.重复步骤4,直到sum < target,重复步骤3
        6.遍历结束后,取到的res即为满足target计和的子序列长度最小的数组长度
        :param nums:
        :param target:
        :return:
        """
        res = float('inf')
        sum = 0
        index = 0
        for i in range(len(nums)): # 窗口右边界,不断右移
            sum += nums[i] # 累加计和
            while sum >= target: # 滑动窗口精髓,只有当累加和大于等于target,取小值长度更新res,sum减去左边界元素,左边界继续右移, 即index++
                res = min(res, i-index+1) # 取长度小值,因为 sum >= target
                sum -= nums[index] # 窗口左边界右移,sum减小, 左边界index右移
                index += 1
        return 0 if res == float('inf') else res


    def minSubArrayLen1(self, nums: [int], target: int) -> int:
        """
        暴力法, 时间O(n^2), 空间O(1)
        思路:
        1.初始化变量,即序列长度
        2.从数组的第一个元素i开始,从该元素取j往后遍历,依次累加计和,每次初始化sum为0(暴力法)
        3.如果sum大于等于target,此时记录其连续序列长度即j-i+1
        4.res即序列长度和sublen比较,取小值,跳出该次遍历
        5.重复2、3、4,直至遍历完所有元素,此时的res就是序列最小的符合条件的长度
        :param nums:
        :param target:
        :return:
        """
        INT_MAX = 2**31 - 1
        res = INT_MAX # 初始化res, 最终结果变量
        for i in range(len(nums)): # 子序列起点i
            sum = 0 # 每次更新其实位置时,置零---暴力法,每次遍历元素,重新置零,表示本轮元素的结果
            for j in range(i, len(nums)): # 设置子序列的终止位置j
                sum += nums[j] # 逐次累加
                if sum >= target: # 子序列和超过target,更新res
                    sublen = j - i + 1 # 子序列长度
                    res = min(res, sublen) # 保持最小的res
                    break # 小者,条件最短的子序列
        return 0 if res == INT_MAX else res # res没有更新,则返回0





if __name__ == "__main__":
    nums = [1,2,3,5,2,1,1,4,1]
    target = 9
    target1 = 13
    test = Solution()
    print(test.minSubArrayLen(nums,target))
    print(test.minSubArrayLen1(nums,target1))

golang

package main

import (
	"fmt"
)

func main() {
	nums := []int{1, 2, 3, 5, 2, 1, 1, 4, 1}
	target := 9
	fmt.Println(minSubArrayLen(target, nums))
}

// 滑动窗口-时间O(n)
func minSubArrayLen(target int, nums []int) int {
	const INT_MAX = int(^uint(0) >> 1)
	var res int = INT_MAX
	var sum int
	var index int = 0
	for i := 0; i < len(nums); i++ {
		sum = sum + nums[i]
		for sum >= target {
			if res < i-index+1 {
				res = res
			} else {
				res = i - index + 1
			}
			sum = sum - nums[index]
			index++
		}
	}
	if res == INT_MAX {
		return 0
	} else {
		return res
	}
}

// 暴力法-时间O(n^2)
func minSubArrayLen1(target int, nums []int) int {
	const INT_MAX = int(^uint(0) >> 1)
	var res int = INT_MAX
	var sum int
	var sublen int
	for i := 0; i < len(nums); i++ {
		sum = 0
		for j := i; j < len(nums); j++ {
			sum = sum + nums[j]
			if sum >= target {
				sublen = j - i + 1
				if res < sublen {
					res = res
				} else {
					res = sublen
				}
				break
			}
		}
	}
	if res == INT_MAX {
		return 0
	} else {
		return res
	}
}
原文地址:https://www.cnblogs.com/davis12/p/15413342.html