leetcode209-长度最小的子数组

leetcode 209
leetcode209-长度最小的子数组_第1张图片

方法1 暴力解法

时间复杂度:O(n2) 空间复杂度:O(1)

使用两层for循环来解答,第一层i表示起始位置,第二层j表示结束位置
起始从0开始不断右移,结束位置从
i开始向后一直累加,直到和>=目标值,此时是以i开头得到的最小长度,那么当前这个初始位置最小长度已拿到,break跳出

var minSubArrayLen = function (target, nums) {
    let result = Infinity; // 初始化无限大值
    let len = nums.length;
    for (let i = 0; i < len; i++) {
        let sum = 0;
        for (let j = i; j < len; j++) {
            sum = sum + nums[j];
            if (sum >= target) {
                result = Math.min(result, j - i + 1);
                // 已经获取到以i开头的最小长度,跳出本次循环
                break; 
            }
        }
    }
    return result === Infinity ? 0 : result;
};

但是好像暴力解答会无法通过leetcode,提示超出时间限制,所以还是选择下一种方法:利用滑动窗口来解决更好,这可以让时间复杂度降低为O(n)
leetcode209-长度最小的子数组_第2张图片

方法2 滑动窗口

时间复杂度:O(n) 空间复杂度:O(1)

利用滑动窗口来解决问题,循环的时候**i**表示结束位置,计算前n项和,如果前n项和>=target,那么移动slow(起始位置)指针,缩小窗口范围,保证当前窗口范围是达到目标的最小长度数组
滑动窗口在双层for循环的基础上减少为一次循环,之所以可以这样做是因为初始位置是可以不用往回走的,也就是说只要查找到了合适的数组范围,那么slow只需要向前移动,不需要回退,因为缩小到了最小范围以后我们会让i++,这时候范围扩大,就把满足条件的范围也扩大,此时从上次截止的slow开始算起,也是满足范围的,不需要slow在从0开始向前走

图片来自代码随想录

var minSubArrayLen = function (target, nums) {
    let sum = 0; // 记录总和
    let result = Infinity; // 记录最小连续数组长度
    let slow = 0; // 起始指针
    for(let i = 0;i<nums.length;i++){
        sum = sum + nums[i];
        while(sum >= target){
            result = Math.min(result,i - slow + 1);
            // 移动起始指针
            sum = sum - nums[slow];
            slow++
        }
    }
    return result === Infinity ? 0 : result;
};

你可能感兴趣的:(算法小课堂,leetcode,数据结构,算法)