leetcode209长度最小的子数组

leetcode209 Minimum Size Subarray Sum

Posted by BY on July 15, 2019

前言

新的一年,好好学习。

正文

问题来源

本问题来自leetcode上的209题。

问题描述

给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组。如果不存在符合条件的连续子数组,返回 0。

示例 :

输入: s = 7, nums = [2,3,1,2,4,3]
输出: 2
解释: 子数组 [4,3] 是该条件下的长度最小的连续子数组。

分析:

自己的代码

func minSubArrayLen(s int, nums []int) int {
    const UINT_MAX = int(^uint(0) >> 1)
    min := UINT_MAX
    if len(nums) == 0 {
        return 0
    }
    if nums[0] >= s {
        return 1
    }
    for i := 1; i < len(nums); i++ {
        nums[i] += nums[i-1]
        if nums[i] >= s {
            if i+1 < min {
                min = i+1
            }
            for j := 0; s <= nums[i] - nums[j]; j++ {
                if i-j < min {
                    min = i - j
                }
            }
        }
    }
    if min == UINT_MAX {
        return 0
    }
    return min
}

思想类似的C++代码


class Solution {
    //时间复杂度 0(n)
    //空间复杂度 O(1)
    public int minSubArrayLen(int s, int[] nums) {
        int n = nums.length;
        int left =0,min = 0,sum = 0;
        for(int i=0;i<n;i++){
            sum+=nums[i];
            while(sum>=s){
                if(min==0){
                    min = i-left+1;
                }else{
                    min = Math.min(i-left+1,min);
                }
                sum -=nums[left];
                left++;
            }
        }
        return min;
    }
}

这个时候我们就会想到之前Leetcode 167:两数之和 II - 输入有序数组提到的对撞指针。我们可以建立两个指针,通过累加两个指针的区间内的值和s比较,就可以在O(n)级别的时间内得到结果。

2 3 1 2 4 3 l <- -> r 1 2 由于两个指针移动的过程中,指针之间的距离就像一个窗口一样,我们通过控制窗口的大小,得到我们想要的结果。我们称这种问题是一个滑动窗口问题。

class Solution:
    def minSubArrayLen(self, s, nums):
        """
        :type s: int
        :type nums: List[int]
        :rtype: int
        """
        l = 0
        r = 0
        sum_all = 0
        nums_len = len(nums)
        minLength = nums_len + 1
        while l < nums_len:
            if r < nums_len and sum_all < s:
                sum_all += nums[r]
                r += 1
            else:
                sum_all -= nums[l]
                l += 1

            if sum_all >= s:
                minLength = min(minLength, r - l)

        if minLength == nums_len + 1:
            return 0

        return minLength

二分变动窗口大小

class Solution:
    def _windowEx(self, nums, size, s):
        sum = 0
        for i, _ in enumerate(nums):
            if i >= size:
                sum -= nums[i - size]

            sum += nums[i]

            if sum >= s:
                return True
        return False

    def minSubArrayLen(self, s, nums):
        """
        :type s: int
        :type nums: List[int]
        :rtype: int
        """
        l = 1
        r = len(nums)
        result = 0
        while l <= r:
            mid = l + (r - l)//2
            if self._windowEx(nums, mid, s):
                r = mid - 1
                result = mid
            else:
                l = mid + 1

        return result

总结:

勤思考。

结语

不管怎么样好好加油。