209、长度最小的子数组

18 阅读2分钟

209. 长度最小的子数组

已解答

中等

相关标签

premium lock icon相关企业

给定一个含有 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] <= 104

 

进阶:

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

题解: 1、想到了使用滑动窗口的思路,但是逻辑比暴力解法复杂,所以理了很久。 现在看其实就两个while,一个是left+,加到sum小于target停止;另一个是right+,加到sum大于target停止。 2、写两个循环时候的边界条件不好设定,特别是数组长度为1或者为0的特殊情况,因此后来选择在函数开始时先处理一些边界,后面的循环不用考虑那么复杂的情况了。这是一个可以沿用的方法,如果边界条件很特殊,可以在开头单独处理掉。

发生的bug:漏了更新sum的值。

    int minSubArrayLen(int target, int* nums, int numsSize) {

        if (numsSize == 0)
        return 0;

        if (nums[0] >= target)
        {
            return 1;
        }

        int left = 0, right = 1;
        int sum = nums[0];
        int lestlen = numsSize;
        int flag = 0;

        while (right <= numsSize - 1)
        {
            sum = sum + nums[right];
            while (left <= right && sum >= target)
            {
                //记录下当前最小长度
                flag = 1;
                if (right - left + 1 < lestlen)
                {
                    lestlen = right - left + 1;
                }

                //继续尝试缩小长度
                sum = sum - nums[left];
                left ++;
            }
            right ++;
            
        }

        if (flag == 1)
        {
            return lestlen;
        }
        else
        return 0;
    }