剑指 Offer II 008. 和大于等于 target 的最短子数组

135 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情

一、题目描述:

给定一个含有 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) 链接:leetcode-cn.com/problems/2V…

二、思路分析:

题目明确表示nums元素都是正整数,

因此对于子数组[l...r]和它的元素和sum:

  • l右移必将导致sum变小
  • r右移比较导致sum变大

那么我们可以使用滑动窗口方法进行求和,滑窗内所有项的和是随着滑窗的范围扩大而稳定增大的,具体思路如下:

当前滑窗内的所有项的和大于等于target 的时候,则往右移动滑窗左边界,缩小滑窗内的和

当当前滑窗内所有项的和小于target的时候,则往右移动滑窗右边界,增加滑窗内各项的和

在不断右移的过程中,找到长度最小的那个区间即可

三、AC 代码:

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int left = 0;
        int right = 0;
        int sum = nums[0];
        int n = nums.length;
        int ans = sum>=target?1:Integer.MAX_VALUE;
        while (true){
            if (sum >= target){
             
                ans = Math.min(ans,right-left+1);
                sum -= nums[left];
                left++;
                if (left> right){
                  
                    right++;
                    if (right>=n){
                     
                        break;
                    }
                    sum += nums[right];
                }
            }else{
             
                right++;
                if (right>=n){
               
                    break;
                }
                sum += nums[right];
            }

        }
        return ans == Integer.MAX_VALUE?0:ans;
    }
}

四、总结:

image.png

掘友们,解题不易,如果觉得有用就留下个赞或评论再走吧!谢啦~ 💐