27.< tag-数组和滑动窗口> -lt.209-长度最小的子数组 1

lt.209-长度最小的子数组

[案例需求]

在这里插入图片描述

[思路分析一, 暴力解法]

  • 使用双重for循环, 外循环遍历整个数组, 内循环从外循环遍历数往后不断叠加, 不断的遍历, 知道满足和 >= target
  • 把每次内循环得到的满足题目要求的子数组的长度跟上一次比较, 记录下较小的值
  • 双重for循环完毕后, 也就得到了长度最小的子数组, 能够满足子数组的和 >= target

[代码实现]

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
       
        int res = Integer.MAX_VALUE;
        for (int i = 0; i < nums.length; i++) {
            int sum = nums[i];
            if (sum >= target)
                return 1;
            for (int j = i + 1; j < nums.length; j++) {
                sum += nums[j];
                if (sum >= target) {
                    res = Math.min(res, j - i + 1);
                    break;
                }
            }
        }
        return res == Integer.MAX_VALUE ? 0 : res;
    
    }
}

在这里插入图片描述
在这里插入图片描述

[思路分析二, 前缀和 + 二分查找]

在这里插入图片描述

[代码实现]

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int n = nums.length;
        if (n == 0) {
            return 0;
        }
        int ans = Integer.MAX_VALUE;
        int[] sums = new int[n + 1]; 
        // 为了方便计算,令 size = n + 1 
        // sums[0] = 0 意味着前 0 个元素的前缀和为 0
        // sums[1] = A[0] 前 1 个元素的前缀和为 A[0]
        // 以此类推
        for (int i = 1; i <= n; i++) {
            sums[i] = sums[i - 1] + nums[i - 1];
        }
        for (int i = 1; i <= n; i++) {
            int tar = target + sums[i - 1];
            int bound = Arrays.binarySearch(sums, tar);
            if (bound < 0) {
                bound = -bound - 1;
            }
            if (bound <= n) {
                ans = Math.min(ans, bound - (i - 1));
            }
        }
        return ans == Integer.MAX_VALUE ? 0 : ans;
    }
}

在这里插入图片描述

[思路分析三, 滑动窗口法]

  • 本题目属于是可变窗口的滑动窗口问题,

    1. 首先我们使用right指针, 遍历整个数组, 寻找可行解(本体的可行解就是数组的和 >= target, 所以直接对right遍历的数进行连加即可);
    2. 在找到可行解之后(窗口满足要求了), 我们使用left 遍历寻找最优解, 在可行解可行的条件前提下, 使用left 向窗口末尾移动, 并记录下窗口缩短时的最优解(本体的最优解是长度最小的子数组, 即长度最小的窗口);
    3. 另外, 因为存在没有可行解的情况, 所以我们需要在返回时进行判断.
  • 详见: tag数组-刷题预备知识-5. 数组中的滑动窗口

[代码实现]

// 最优, 滑动窗口
class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        //连续子数组, 求长度最小的满足和 >= target
        //应用非固定滑动窗口求解
        //双指针, right寻找可行解, left 寻找最优解
        int left = 0;
        int right = 0;
        int len = nums.length;

        int sum = 0;

        int res = Integer.MAX_VALUE; // 记录每个窗口的最小窗口值
        while(right < len){
            //right移动, 数字添加到窗口
            sum += nums[right];
            
            //窗口满足要求
            while(sum >= target){
                //寻找最优解;
                res = Math.min(res, right - left + 1);
                sum -= nums[left];
                ++left;
            }

            ++right; // 注意
        }

        return res == Integer.MAX_VALUE ? 0 : res;
    }
}
posted @   青松城  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示