Leetcode刷题-209:长度最小的子数组

本文介绍了如何使用暴力解法和双指针法(滑动窗口)解决LeetCode上的一道题目,目标是找到数组中最小子数组的长度,使其和大于或等于给定的目标值。通过分析两种方法,展示了如何在O(N^2)的时间复杂度和O(N)的时间复杂度下解决问题,并提供了相应的C++代码实现。双指针法通过移动左指针更新子数组和,减少了时间复杂度,提高了效率。
摘要由CSDN通过智能技术生成

1.题目描述

给定一个含有 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 = 11, nums = [1,1,1,1,1,1,1,1]
输出:0

来源:力扣(LeetCode)

2.题目分析

2.1 暴力解法

因为数组全为正整数,所以可以得出在固定起始端点的时候子数组越长得到的子数组和就越大。因而我们就很容易可以想到时间复杂度为O(N2)的暴力解法。具体来说就是每次确定子数组起始点为i后,从i开始逐步遍历(一步一步增长子数组长度),直到nums[i]+...nums[j]>=target时退出本轮循环,此时的j-i+1就是此次的子数组长度。
具体代码见第3.1部分。

2.2 双指针法

一般数组之类的问题都可以考虑使用双指针法来解决,本题也一样。我们回到问题本身是求一个子数组,其实也就是求一个满足区间内所有的数的和大于等于target的子区间[i,j]。这样的话我们就可以以i和j作为两个指针分别指向子数组头尾来进行操作。
这种方法的基本思想是与暴力求解法类似,从数组维护一个子区间[i,j]。不同的是此时我们只有一次循环,也就是说只根据一个指针来进行循环,具体是每当区间的和大于target时,我们就移动i指针但是j指针在其原本位置不变,不用再像穷举一样回到i指针后面。下面是其求解步骤:

  1. 首先初始化i指针指向数组首部,确定参数res记录最短长度,sum记录子数组和
  2. 声明指针j从头至尾循环数组,sublength记录子数组长度
  3. 每当当前区间内元素和大于target,就更新sublengthj-i+1),并决定是否更新res(检查是否更短),再将sum子数组和进行更新(此时i元素被排除)

3.题目解答

1)暴力解法

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int n = nums.size();
        int sublength = n;
        int result = n+1;
        for(int i=0;i<n;i++){
            int sums = 0;
            for(int j=i;j<n;j++){
                sums+=nums[j];
                if(sums>=target){
                    sublength = j-i+1;
                    result = result<sublength?result:sublength;
                    break;
                }
            }
        }
        return result==n+1?0:result;
    }
};

2)双指针法——滑动窗口

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int n = nums.size();
        int sublength = n;
        int result = n+1;
        int sum = 0;
        int i=0;
        for(int j=0;j<n;j++){
            sum+=nums[j];
            //华东窗口的移动,在这里只移动左端,因为右端做循环操作
            while(sum>=target){
                sublength = j-i+1;
                result = result<sublength?result:sublength;
                sum -= nums[i++];
            }
        }
        return result==n+1?0:result;
    }
};

总结:本体也可以用前缀数组(参考560题)的方式来解决

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值