算法题型:滑动窗口(leetcode 209)

一、209. 长度最小的子数组

难度中等

题目描述

给定一个含有 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组如果不存在符合条件的连续子数组,返回 0。

示例: 

输入: s = 7, nums = [2,3,1,2,4,3]
输出: 2
解释: 子数组 [4,3] 是该条件下的长度最小的连续子数组。

 分析:采用滑动窗口,i,j分别表示左边界和右边界,sto用来存储i-j之间数值的和,res用来存储j-i。

最外层循环判定循环结束,即左侧边界到达倒数第二个位置(因为默认j一定在i的右边)

当sto<s&&j<len的时候右边界右移,否则(j到达最右边,或者sto>=s)移动左边界

res则不停的判断是否有更小的距离,前提条件都是:

if(sto>=s){
       res=Math.min(res,j-i);
 }

class Solution {
    public int minSubArrayLen(int s, int[] nums) {
        int len=nums.length;
        if(len==0)return 0;
        int i=0;
        int j=1;
        int res=len+1;
        int sto=nums[0];//用于存储当前添加值
        while(i<len-1){
            if(sto<s&&j<len){
                sto+=nums[j];
                j++;
            }
            else {
                if(sto>=s){
                res=Math.min(res,j-i);
                }
                i++;
                sto-=nums[i-1];
            }   
        }
        if(res==len+1)res=0;
        return res;
    }
}

二、剑指offer(63) 滑动窗口的最大值

1.题目描述

给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。
例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,
他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个:
 {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1},
  {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。

2.分析
 

我的解法:
1.设立两个用于比较的值,maxValue和maxIndex,指示当前用于比较的最大值以及他的下标
2.先对第一个滑动窗口进行比对,得出maxValue=4,maxIndex=2,并添加到ArrayList中
    {[2,3,4],2,6,2,5,1}
3.然后从index=3的位置逐步往后比较maxValue的值,遇到更大的就替换maxValue和maxIndex为新的值
    {2,3,[4,2,6],2,5,1},如第三个滑动窗口,maxValue替换为6,maxIndex替换为4
    依此类推......
4.这个过程可能会遇到,超出当前maxValue的比对范围的情况,
    如:{2,3,4,2,6,[2,5,1]}
    maxValue=6,maxIndex=4,但是现在已经到"1"所在的位置,超出了窗口范围
    因此采用一层循环,从"2"~"5"之间,重新设定maxVlue和maxIndex
5.从头遍历到尾,每次循环将maxValue添加到ArrayList中。(要注意边界条件 size<=0||len<=0||size>len)
 

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> maxInWindows(int [] num, int size)
    {
        ArrayList<Integer> memo = new ArrayList<>();
        int len = num.length;
        //牛客网几乎所有不符合条件的都是返回空,务必要注意
        if(size<=0||len<=0||size>len)return memo;
        int maxValue = Integer.MIN_VALUE;
        int maxIndex = -1;
        for(int i=0;i<size;i++){
            if(i<len&&num[i]>maxValue){
                maxValue = num[i];
                maxIndex = i;
            }
        }
        //可以判断,如果size<=0,保证memo为null
        if(maxIndex!=-1){
            memo.add(maxValue);
        }

        for(int i=size;i<len;i++){
            //如果超出前面最大值的比较范围,则需要重新设定
            //以下循环,判断到i之前的一个最大值
            if(i-maxIndex>=size){
                int j = i-size+1;
                maxValue = num[j];
                while(j<i){
                    if(num[j]>maxValue){
                        maxValue = num[j];
                        maxIndex = j ;
                    }
                    j++;
                }
            }
            if(num[i]>maxValue){
                maxValue = num[i];
                maxIndex = i;
            }
            memo.add(maxValue);
        }
        return memo;
    }
}

其他解法:

待补充!

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
滑动窗口是一种常用的算法技巧,可以用于解决一类问题,其中包括一些LeetCode上的题目。通过维护一个窗口,我们可以在线性时间内解决一些需要处理连续子数组或子字符串的问题。以下是一些常见的滑动窗口问题: 1. 最小覆盖子串(Minimum Window Substring):给定一个字符串S和一个字符串T,在S中找出包含T所有字符的最小子串。 2. 字符串的排列(Permutation in String):给定两个字符串s1和s2,判断s2是否包含s1的排列。 3. 找到字符串中所有字母异位词(Find All Anagrams in a String):给定一个字符串s和一个非空字符串p,找到s中所有是p的字母异位词的子串。 4. 替换后的最长重复字符(Longest Repeating Character Replacement):给定一个只包含大写英文字母的字符串s,你可以将一个字母替换成任意其他字母,使得包含重复字母的最长子串的长度最大化。 5. 至多包含两个不同字符的最长子串(Longest Substring with At Most Two Distinct Characters):给定一个字符串s,找出至多包含两个不同字符的最长子串的长度。 以上只是几个例子,滑动窗口可以应用于更多类型的问题。在解决这些问题时,我们通常使用两个指针来表示窗口的左右边界,并根据具体问题的要求移动窗口。在每次移动窗口时,我们可以更新窗口的状态,例如统计字符出现次数、判断窗口是否满足条件等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IMUHERO

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值