力扣labuladong一刷day20天滑动窗口共4题

力扣labuladong一刷day20天滑动窗口共4题

文章目录

      • 力扣labuladong一刷day20天滑动窗口共4题
      • 一、76. 最小覆盖子串
      • 二、567. 字符串的排列
      • 三、438. 找到字符串中所有字母异位词
      • 四、3. 无重复字符的最长子串

一、76. 最小覆盖子串

题目链接:https://leetcode.cn/problems/minimum-window-substring/
思路:使用一个needmap记录target中字符的数量,然后用一个windowmap开始收集字符串s中的字符,当条件满足时,就可以开始缩小滑动窗口,并在过程中记录最小子串长度,条件不满足了就退出缩小,继续扩大窗口,以此往复。

class Solution {
     public String minWindow(String s, String t) {
        Map<Character, Integer> window = new HashMap<>();
        Map<Character, Integer> need = new HashMap<>();

        for (char c : t.toCharArray()) {
            need.put(c, need.getOrDefault(c, 0) + 1);
        }
        int left = 0, right = 0, valid = 0, init = 0;
        int min = Integer.MAX_VALUE;
        while (right < s.length()) {
            char rc = s.charAt(right);
            right++;
            if (need.containsKey(rc)) {
                window.put(rc, window.getOrDefault(rc, 0) + 1);
                if (window.get(rc).equals(need.get(rc))) {
                    valid++;
                }
            }
            while (valid == need.size()) {
                if (right - left < min) {
                    min = right - left;
                    init = left;
                }
                char lc = s.charAt(left);
                left++;
                if (need.containsKey(lc)) {
                    if (need.get(lc).equals(window.get(lc))) {
                        valid--;
                    }
                    window.put(lc, window.get(lc)-1);
                }
            }
        }
        return min == Integer.MAX_VALUE ? "" : s.substring(init, init+min);
    }
}

二、567. 字符串的排列

题目链接:https://leetcode.cn/problems/permutation-in-string/
思路:一样是滑动窗口,要求s1的排列是否包含在s2中,其实滑动窗口只要维持和s1的长度相等即可,然后判断这个窗口内元素的个数是否满足。

class Solution {
    public boolean checkInclusion(String s1, String s2) {
        Map<Character, Integer> need = new HashMap<>();
        Map<Character, Integer> window = new HashMap<>();
        for (char c : s1.toCharArray()) {
            need.put(c, need.getOrDefault(c, 0)+1);
        }
        int left = 0, right = 0, valid = 0;
        while (right < s2.length()) {
            char rc = s2.charAt(right);
            right++;
            if (need.containsKey(rc)) {
                window.put(rc, window.getOrDefault(rc, 0)+1);
                if (window.get(rc).equals(need.get(rc))) {
                    valid++;
                }
            }
            if (right - left == s1.length()) {
                if (valid == need.size()) return true;
                char lc = s2.charAt(left);
                left++;
                if (need.containsKey(lc)) {
                    if (need.get(lc).equals(window.get(lc))) {
                        valid--;
                    }
                    window.put(lc, window.get(lc)-1);
                }
            }
        }
        return false;
    }
}

三、438. 找到字符串中所有字母异位词

题目链接:https://leetcode.cn/problems/find-all-anagrams-in-a-string/
思路:也是滑动窗口,这个找异位词和上一题很类似,只不过上一题就一个,这题是有多个然后收集起始位置。

class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        List<Integer> list = new ArrayList<>();
        Map<Character, Integer> need = new HashMap<>();
        Map<Character, Integer> window = new HashMap<>();
        for (char c : p.toCharArray()) {
            need.put(c, need.getOrDefault(c, 0)+1);
        }
        int left = 0, right = 0, valid = 0;
        while (right < s.length()) {
            char rc = s.charAt(right);
            right++;
            if (need.containsKey(rc)) {
                window.put(rc, window.getOrDefault(rc, 0)+1);
                if (window.get(rc).equals(need.get(rc))) {
                    valid++;
                }
            }
            if (right - left == p.length()) {
                if (valid == need.size()) {
                    list.add(left);
                }
                char lc = s.charAt(left);
                left++;
                if (need.containsKey(lc)) {
                    if (window.get(lc).equals(need.get(lc))) {
                        valid--;
                    }
                    window.put(lc, window.get(lc)-1);
                }
            }
        }
        return list;
    }
}

四、3. 无重复字符的最长子串

题目链接:https://leetcode.cn/problems/longest-substring-without-repeating-characters/
思路:求无重复字符的最长子串,扩大窗口时只需要一直往里放即可,如果当前元素添加后数量大于1,就要开始收缩窗口,直到当前元素个数不再大于1,期间窗口每扩大一步就更新一次最大值。

class Solution {
  public int lengthOfLongestSubstring(String s) {
        Map<Character, Integer> window = new HashMap<>();
        int left = 0, right = 0;
        int max = 0;
        while (right < s.length()) {
            char rc = s.charAt(right);
            right++;
            window.put(rc, window.getOrDefault(rc, 0)+1);

            while (window.get(rc) > 1) {
                char lc = s.charAt(left);
                left++;
                window.put(lc, window.get(lc)-1);
            }
            max = Math.max(max, right-left);
        }
        return max;
    }
}

你可能感兴趣的:(力扣算法题,leetcode,算法,职场和发展,滑动窗口)