java滑动窗口法,运行1ms(题209最短子数组)

48 篇文章 0 订阅
8 篇文章 0 订阅

一、问题描述

长度最小的子数组

CategoryDifficultyLikesDislikes
algorithmsMedium (48.18%)967-
Tags Companies

给定一个含有 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)) 时间复杂度的解法。

二、xin麒的思路

本题解使用了滑动窗口法,

摘要:

  • 滑动窗口法的精髓就是在于外层循环不断遍历,寻找出一个符合题目要求的子数组,内层循环将子数组优化:剔除重复的元素。

前提引入:

    • 定义sum变量保存累加的数组,方便与target比较;
    • 使用变量count保存合适的长度(初始值为nums.lengh方便后面的比较)
    • 使用变量note来记录,解决没有子数组的情况(如果note始终为0,那么说明nums里找不到符合的子数组)
    • start指针从0开始

分析:

  • 首先使用end作为指针遍历,遍历时,不断进行sum += nums[end]使得sum增加;

    • 待sum大于或等于target时,这时候**(end - start + 1 )的数值一定是该end值对应的子数组的长度吗?如果sum[end]远大于target,那么显然此时的(end - start + 1 )对应的数值偏大了,于是需要让start**增大,同时sum的数值适当减小(减小到刚刚sum < target即可)
  • 于是构造一层内部的while循环,该循环实现功能有:

    • 使得每次sum都要不断减小
    • 同时start增大到合适的值

    根据上述分析,可知循环条件为sum >= target

  • 由于内层循环退出后需要让count保存此刻子数组的长度,那么子数组的长度**(end - start + 1 )还是(end - start + 2 )呢?显然,由于此时退出循环时sum已经小于target了,那么此时end对应的子数组应该是由索引在区间[start-1,end]的元素构成,那么长度就是(end - start + 2 )**;

    每次找到不同的长度,就通过与count比较,取小的作为count

三、xin麒的题解:

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int start = 0;
        int size = nums.length;
        int count = size;
        int sum = 0;
        int note = 0;
        for (int end = 0; end < size; end++) {
            sum += nums[end];
            if (sum >= target){
                note = 1;
                while (sum >= target){
                    sum -= nums[start++];
                }
                int number = end - start + 2;
                if (count > number){
                    count = number;
                }
            }
        }
        if (note == 0){
            return 0;
        }
        return count;
    }
}
运行:

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值