209. Minimum Size Subarray Sum

209Minimum Size Subarray Sum

题目描述

 

Given an array of n positive integers and a positive integer s, find the minimal length of a contiguous subarray of which the sum ≥ s. If there isn't one, return 0 instead.

For example, given the array [2,3,1,2,4,3] and s = 7, the subarray [4,3] has the minimal length under the problem constraint.

More practice:

If you have figured out the O(n) solution, try coding another solution of which the time complexity is O(n log n).

分析

O(n)解法:

要求在数组中寻找含有最少元素的连续子数组,满足其和为s。

  • 使用left和right两个指针,分别作为欲寻找子数组的两端,初始化时,均指向第一个元素;
  • 然后将数组中的元素依次加入结果数组,记录和,
    • 若和total大于等于s,或者 right 达到数组末尾,此时我们更新最短距离,并且将 left 像右移一位,然后在 sum 中减去移去的值
    • 若和total小于s,则右端点左移。
    • 然后重复上面的步骤,直到 right 到达末尾,且 left 到达临界位置,即要么到达边界,要么再往右移动,和就会小于给定值。 

class Solution(object):
    def minSubArrayLen(self, s, nums):
        """
        :type s: int
        :type nums: List[int]
        :rtype: int
        """
        # O(n)解法
        if not s or nums == []:
            return 0
        total = 0
        left = 0
        res = len(nums)+1
        # 右指针从左向右依次遍历数组中的元素
        for right,n in enumerate(nums):
            total += n
            # 循环右移左指针
            # 并且需要符合和大于s,左指针小于右指针
            while total>=s and left<=right:
                res = min(res, right-left+1)
                total -= nums[left]
                left += 1
        # 注意返回值的过滤方式
        return res if res<=len(nums) else 0

O(nlogn)解法:

采用分治法,在区间中寻找适当的可以构成答案的子区间。

1. 每两个相邻元素求和,结果保存在较大索引中,最终每个索引中存储的是从头到该索引的所有数字之和;

2. 当当前的求和大于目标值时,需要更新左起点;调用二分查找的子函数来更新。

3. 更新最小距离,并按照判断条件进行返回。

 

class Solution(object):
    def minSubArrayLen(self, s, nums):
        """
        :type s: int
        :type nums: List[int]
        :rtype: int
        """
        result=len(nums)+1
        for idx, n in enumerate(nums[1:], 1):
            nums[idx] = nums[idx - 1] + n   #每两个相邻值求和,‘和’保存在较大索引的数里,nums[idx]为nums数组前idx+1个数的和
        left=0
        for right,n in enumerate(nums):     
            if n >= s:    #当前索引下的求和大于欲寻找的元素和,则需要更新起点(左端点)
                left=self.find_left(left,right,nums,s,n)
                result=min(result,right-left+1)
        return result if result<=len(nums) else 0
    
    #分治法/二分搜索
    def find_left(self,left,right,nums,s,n):
        while left<right:           #终止条件:left>=right
            mid=(left+right)//2     #寻找区间的中点
            if n-nums[mid] >= s:    #若当前和-区间前半部分的和仍大于欲寻找的和,欲寻找的左端点在区间的右半部分
                left=mid+1          #更新起点(左端点)
            else:                   #若当前和-区间前半部分的和小于欲寻找的和,欲寻找的左端点在区间的左半部分
                right=mid           #更新终点(右端点)
        return left                 #返回起点
This problem can be solved using binary search. We can try to find the minimum possible maximum sum in a subarray by binary searching over the range of possible values. The upper bound of this range is the sum of all elements in the array, since each subarray must have at least one element. The lower bound of this range is the maximum element in the array, since each subarray must have at least one element and the maximum element must be in its own subarray. For each guess of the maximum sum, we can try to divide the array into subarrays such that no subarray has a sum greater than the guess. This can be done by iterating through the array and greedily assigning each element to the current subarray until the sum of the subarray is greater than the guess. Then, we start a new subarray with the current element. If we can divide the array into k subarrays with a maximum sum no greater than our guess, we can try a smaller guess. If we cannot divide the array into k subarrays with a maximum sum no greater than our guess, we need to try a larger guess. Here's some sample code in Python: ``` n, k = map(int, input().split()) arr = list(map(int, input().split())) low = max(arr) high = sum(arr) while low < high: mid = (low + high) // 2 count = 1 total = 0 for x in arr: if total + x > mid: count += 1 total = x else: total += x if count > k: low = mid + 1 else: high = mid print(low) ``` This code reads in the input and initializes the range of possible values for the maximum sum in a subarray. Then, it performs binary search to find the minimum possible maximum sum. For each guess of the maximum sum, it tries to divide the array into k subarrays such that no subarray has a sum greater than the guess. If it can do this, it tries a smaller guess. If not, it tries a larger guess. Finally, it prints out the minimum possible maximum sum.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值