滑动窗口解决leetcode的最小覆盖子串问题:
除了窗口更新和minDiff计算,其他都是框架。最关键的是valid的理解,就是判断window是否包含了need的所有内容。
package com.company;
import java.util.HashMap;
import java.util.Map;
public class SlideWindow {
public static void main(String[] args) {
String src = "ebbancf";
String target = "abc";
System.out.println(new SlideWindow().slideWindow(src, target));
}
public String slideWindow(String source, String target) {
Map<Character, Integer> need = new HashMap<>(); //需要的字符及其个数
Map<Character, Integer> window = new HashMap<>(); //窗口内符合的字符及其个数
for (Character c : target.toCharArray()) {
need.put(c, need.getOrDefault(c, 0) + 1); //初始化need
}
int left = 0;
int right = 0;
int valid = 0;
int minDiff = Integer.MAX_VALUE;
int minLeft = left;
int minRight = right;
while (right < source.length()) {
Character c = source.charAt(right); //c是将移入窗口的字符
right++;
//进行窗口内数据的一系列更新
if (need.containsKey(c)) {
window.put(c, window.getOrDefault(c, 0) + 1); //加入窗口,并增加字符数
if (window.get(c).equals(need.get(c))) {
valid++;
}
}
//debug输出的位置
System.out.println("left: " + left + " right: " + right);
//判断左侧窗口是否要收缩
while (valid == need.size()) {
if (minDiff > right - left) {
minLeft = left;
minRight = right;
minDiff = right - left;
}
//d是将移出窗口的字符
char d = source.charAt(left);
//左移窗口
left++;
//进行窗口内数据的一系列更新
if (need.containsKey(d)) {
if (window.get(d).equals(need.get(d))) {
valid--;
}
window.put(d, window.get(d) - 1);
}
}
System.out.println("minLeft: " + minLeft + " minRight: " + minRight);
}
return minDiff == Integer.MAX_VALUE ? "" : source.substring(minLeft, minRight);
}
}