滑动窗口通用模板及解题方法

 求最短x模板

//求最短x模板:
初始化left,right,result,baseResult、
while(右指针没有到结尾){
    窗口扩大,加入right对应元素,更新当前result
    while(result满足要求){
        更新最优结果bestResult
        窗口缩小,移除left对应元素,left右移
    }
    right++;
}
返bestResult;

求最长x模板 

初始化left,right,result,bestResultwhile

while(右指针没有到结尾) {
{
    窗口扩大,加入right对应元素,更新当前resultwhile     

    while(result不满足要求)

        {
           窗口缩小,移除left对应元素,left右移
        }

         更新最优结果bestResult

         right++;
}
返回bestResult; 

这两个模板区块在求最短的是把  更新最优结果bestResult这部分放在第二个while循环里面,求最长的是放在第一个while循环里面。

例题:无重复字符的最长子串

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 2:

输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

示例 3:

输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
     请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串

这用滑动窗口最长x的模板来求 

import java.util.*;

class Solution {
    public int lengthOfLongestSubstring(String s) {
        int left = 0; // 定义滑动窗口的左指针
        int right = 0; // 定义滑动窗口的右指针
        Map<Character, Integer> symbol = new HashMap(); // 使用HashMap存储字符及其出现的次数
        char[] str = s.toCharArray(); // 将输入的字符串转换为字符数组
        int result = 0; // 当前滑动窗口的长度
        int baseResult = 0; // 最长不重复子串的长度

        while (right < s.length()) { // 右指针未到达字符串末尾时循环
            symbol.put(str[right], symbol.getOrDefault(str[right], 0) + 1); // 更新字符出现的次数
            result++; // 滑动窗口长度加一

            while (symbol.get(str[right]) > 1) { // 当出现重复字符时
                symbol.put(str[left], symbol.get(str[left]) - 1); // 左指针指向的字符出现次数减一
                result--; // 滑动窗口长度减一
                left++; // 左指针向右移动
            }

            baseResult = Math.max(baseResult, result); // 更新最长不重复子串的长度
            right++; // 右指针向右移动
        }

        return baseResult; // 返回最长不重复子串的长度
    }
}

模板

public List<Integer> moudleFun(String s, String p) {
    List<Integer> result = new ArrayList<>();
    Map<Character, Integer> need = new HashMap<>(p.length());
    Map<Character, Integer> window = new HashMap<>(p.length());
    for (int i = 0; i < p.length(); i++) {
        need.put(p.charAt(i), need.getOrDefault(p.charAt(i), 0) + 1);
    }
    int left = 0, right = 0;
    int valid = 0;
    while (right < s.length()) {
        char cur = s.charAt(right);
        right++;
        // 进行窗口内数据的一系列更新
        ...
        // 判断左侧窗口是否要收缩
        while (right - left >= p.length()) {
            // 当窗口符合条件时,把起始索引加入 result 中
            if (valid == need.size()) {
                result.add(left);
            }
            char d = s.charAt(left);
            left++;
            // 进行窗口数据当一系列更新
            ...
        }
    }
    return result;
}

题目

LCR 017. 最小覆盖子串

给定两个字符串 s 和 t 。返回 s 中包含 t 的所有字符的最短子字符串。如果 s 中不存在符合条件的子字符串,则返回空字符串 "" 。

如果 s 中存在多个符合条件的子字符串,返回任意一个。

注意: 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。

示例 1:

输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC" 
解释:最短子字符串 "BANC" 包含了字符串 t 的所有字符 'A'、'B'、'C'
class Solution {
     public String minWindow(String s, String t) {
        // 存储目标字符及其出现次数
        Map<Character, Integer> need = new HashMap<>();
        // 存储窗口内字符及其出现次数
        Map<Character, Integer> window = new HashMap<>();

        // 初始化need
        for (char c : t.toCharArray()) {
            need.put(c, need.getOrDefault(c, 0) + 1);
        }

        int left = 0, right = 0;
        int valid = 0;
        int start = 0, len = Integer.MAX_VALUE;

        while (right < s.length()) {
            // c 是将移入窗口的字符
            char c = s.charAt(right);
            // 右移窗口
            right++;

            // 进行窗口内数据的一系列更新
            if (need.containsKey(c)) {
                window.put(c, window.getOrDefault(c, 0) + 1);
                if (window.get(c).equals(need.get(c))) {
                    valid++;
                }
            }

            // 判断左侧窗口是否要收缩
            while (valid == need.size()) {
                // 在这里更新最小覆盖子串
                if (right - left < len) {
                    start = left;
                    len = right - left;
                }

                // d 是将移出窗口的字符
                char d = s.charAt(left);
                // 左移窗口
                left++;

                // 进行窗口内数据的一系列更新
                if (need.containsKey(d)) {
                    if (window.get(d).equals(need.get(d))) {
                        valid--;
                    }
                    window.put(d, window.get(d) - 1);
                }
            }
        }

        // 返回最小覆盖子串
        return len == Integer.MAX_VALUE ? "" : s.substring(start, start + len);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_20314141/article/details/134764878