暑假算法刷题日记 Day 8

前言

今天我们的题都是关于滑动窗口的,首先我们先来介绍一下滑动窗口是什么。

滑动窗口

滑动窗口其实也是一种双指针,用于解决数组问题中,查找某个连续子数组中最值的一种解决办法。其核心思路是右指针每次向右遍历,给窗口扩大,然后检查此时窗口是否符合条件,如果符合,就收缩直至不符合,收缩过程记得更新窗口相关的变量。更新之前或者之后一般要寻找最佳答案,我们根据下面的题目进行具体分析。

int l=0;//滑动窗口左端点
for(int i=0;i<nums.length;i++){//滑动窗口右端点
	//扩张阶段
	...
	//收缩阶段
	while(check()){
	...
	}
}

题目

038、长度最小的子数组

题目描述

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其总和大于等于 target 的长度最小的
子数组
[numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

解题思路

我们用一个sum记录窗口中元素的和,收缩的条件就是sum>=target

代码

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int l=0;
        int len=nums.length;
        int ans=Integer.MAX_VALUE;
        long sum=0;
        for(int r=0;r<len;r++){
        	//扩张
            sum+=nums[r];
            //收缩
            while(sum>=target){
            	//寻找最佳答案
                ans=Math.min(ans,r-l+1);
                //更新窗口相关的变量
                sum-=nums[l++];
            }
            
        }
        if(ans==Integer.MAX_VALUE)return 0;
        return ans;
    }
}

039、水果成篮

题目描述

你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。

你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:

你只有 两个 篮子,并且每个篮子只能装 单一类型 的水果。每个篮子能够装的水果总量没有限制。
你可以选择任意一棵树开始采摘,你必须从 每棵 树(包括开始采摘的树)上 恰好摘一个水果 。采摘的水果应当符合篮子中的水果类型。每采摘一次,你将会向右移动到下一棵树,并继续采摘。
一旦你走到某棵树前,但水果不符合篮子的水果类型,那么就必须停止采摘。
给你一个整数数组 fruits ,返回你可以收集的水果的 最大 数目。

解题思路

分析一下,我们要做其实是看一段连续数组中,最多两种水果的数目之和的最大值,肯定还是滑动窗口来做。
我们用一个HashMap记录窗口中水果的种类及数量,收缩的条件就是map.size()>2

代码

class Solution {
    public int totalFruit(int[] fruits) {
        int l=0,r=0;
        int len= fruits.length;
        Map<Integer,Integer> mp=new HashMap<>();
        int temp=0;
        int ans=0;
        for(r=0;r<len;r++){
        	//扩张
            mp.put(fruits[r],mp.getOrDefault(fruits[r],0)+1);
            //收缩
            while(mp.size()>2){
                temp=mp.get(fruits[l]);
                mp.put(fruits[l],temp-1);
                if(temp-1==0)mp.remove(fruits[l]);
                l++;
            }
            //寻找答案
            int sum=0;
            for(Integer v:mp.values()){
                sum+=v;
            }
            ans=Math.max(sum,ans);
        }
        return ans;
    }
}

040、最小覆盖子串

题目描述

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。

解题思路

分析一下,我们要做其实是看s的一段连续子串中,是否出现了t中的全部字母及个数。我首先想到的使用哈希表记录字母和个数,肯定还是滑动窗口来做。
我们用一个HashMap mps记录窗口中的字母以及个数,用一个HashMap mpt记录t串中的字母以及个数,收缩的条件(check)就是mps包含mpt中的所有元素,并且value不小于mpt的value。

代码

class Solution {
	//定义全局变量,方便其他方法使用
    Map<Character,Integer> mps=new HashMap<>();
    Map<Character,Integer> mpt=new HashMap<>();
	
    public  boolean check(){
        
        for(Character c:mpt.keySet()){
            
            if(mps.get(c)==null)return false;
            
            if(mps.get(c)<mpt.get(c)){
                return false;
            }
        }
        
        return true;
    }
    public  String minWindow(String s, String t) {

        int l=0,len=s.length();
        int ansl=0,ansr=Integer.MAX_VALUE;
        //初始化mpt
        char[] tt=t.toCharArray();
        for(char c:tt){
            if(mpt.get(c)==null){
                mpt.put(c,1);
            }else{
                mpt.put(c,mpt.get(c)+1);
            }
        }
        //开始滑动
        for(int r=0;r<len;r++){
        	//扩张
            mps.put(s.charAt(r),mps.getOrDefault(s.charAt(r),0)+1);
            //收缩
            while(check()){
            	//记录答案的起止
                if((r-l)<(ansr-ansl)){
                    ansl=l;
                    ansr=r;
                }
                mps.put(s.charAt(l),mps.get(s.charAt(l))-1);
                if(mps.get(s.charAt(l))==0)mps.remove(s.charAt(l));
                l++;
            }
        }
        if(ansr==Integer.MAX_VALUE)return "";
        return s.substring(ansl,ansr+1);
    }
}

结语

暑假已经不足一半,希望能够刷够一百题
请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值