Day83(滑动窗口)

滑动窗口详解 - 知乎 (zhihu.com)

分类:窗口有两类,一种是固定大小类的窗口,一类是大小动态变化的窗口。

应用:什么情况可以用滑动窗口来解决实际问题呢?

  1. 一般给出的数据结构是数组或者字符串
  2. 求取某个子串或者子序列最长最短等最值问题或者求某个目标值时(子序列也有可能是动态规划的解法所以要区分,动态规划求子序列基本是求几种方法/最长长度)
  3. 该问题本身可以通过暴力求解

 209、长度最小的子数组

给定一个含有 n 个正整数的数组和一个正整数 target 。找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl,numsl+1, ..., numsr-1, numsr] ,并返回其长度如果不存在符合条件的子数组,返回 0 。

 

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int left=0,right=0;
        int sum=0;
        int res=Integer.MAX_VALUE;
        while(right<nums.length){
            sum+=nums[right];
            right++;
            while(sum>=target){
                res=Math.min(res,right-left);
                sum-=nums[left];
                left++;
            }
        }
        return res==Integer.MAX_VALUE?0:res;
    }
}

438、找到字符串中所有字母异位词 (比其他题要有相对复杂的细节考虑)

给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。

重要的细节都在代码注释上了 

class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        List<Integer>list=new ArrayList<>();
        Map<Character,Integer>map=new HashMap<>();
        Map<Character,Integer>window=new HashMap<>();

        char ch[]= p.toCharArray();
        //p的各个字符的次数记录
        for(char c:ch){
            map.put(c,map.getOrDefault(c,0)+1);
        }

        int left=0,right=0;
        int sum=0;//记录每一个字母的个数
        while(right<s.length()){
            char c=s.charAt(right);
            right++;
            if (map.containsKey(c)) {//map只添加跟异位词有关的字符,不添加其他的
                window.put(c, window.getOrDefault(c, 0) + 1);
                // 不能写== 比较的是两个地址!!!(就无脑用equals吧)
                if (map.get(c).equals(window.get(c))) {
                    sum++;
                }
            }

            while ((right - left) >= p.length()) {
                if (sum == map.size()) {
                    //注意这里是sum==map.size()而不是sum==p.length()
                    //s="baa"
                    //p="aa"
                    list.add(left);//进行操作
                }
                char temp = s.charAt(left);
                left++;//收缩窗口
                if (map.containsKey(temp)) {
                    //s=cba p=cc 输出是0——>要有如下if的判断,sum才--
                    if (map.get(temp).equals(window.get(temp))) {
                        sum--;
                    }
                    window.put(temp, window.getOrDefault(temp, 0) - 1);
                }
            }
        }
        return list;
    }
}

1208、尽可能使字符串相等

给你两个长度相同的字符串,s 和 t。将 s 中的第 i 个字符变到 t 中的第 i 个字符需要 |s[i] - t[i]|开销(开销可能为 0),也就是两个字符的 ASCII 码值的差的绝对值。
用于变更字符串的最大预算是 maxCost。在转化字符串时,总开销应当小于等于该预算,这也意味着字符串的转化可能是不完全的。如果你可以将 s 的子字符串转化为它在 t 中对应的子字符串,则返回可以转化的最大长度。如果 s 中没有子字符串可以转化成 t 中对应的子字符串,则返回 0

 

class Solution {
    public int equalSubstring(String s, String t, int maxCost) {
        int left=0,right=0;
        int sum=0;//记录转化字符的总开销
        int res=0;
        while(right<s.length()){
            sum+=Math.abs(s.charAt(right)-t.charAt(right));
            right++;
            while(sum>maxCost){
                sum-=Math.abs(s.charAt(left)-t.charAt(left));
                left++;
            }
            //转化后的最大长度
            res=Math.max(res,right-left);
        }
        return res;

    }
}

 1456、定长子串中元音的最大数目

给你字符串 s 和整数 k 。请返回字符串 s 中长度为 k 的单个子字符串中可能包含的最大元音字母数。英文中的 元音字母 为(aeiou)。

 

class Solution {
    public int maxVowels(String s, int k) {
        int left=0,right=0;
        int sum=0;//记录元音字母的个数
        int res=0;
        while(right<s.length()){
            sum+=isVowel(s.charAt(right));
            right++;
            while((right-left)>=k){
                //当窗口长度≥k,则计算此时的子字符串的最大元音字母
                res=Math.max(res,sum);
                sum-=isVowel(s.charAt(left));
                left++;
            }
        }
        return res;

    }

    //判断是否是元音字母
     public int isVowel(char ch) {
        return ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u' ? 1 : 0;
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值