El tema es de LeetCode
76. Subcadena de cobertura mínima
Se puede acceder a otras soluciones o código fuente: tongji4m3
descripción
Te doy una cuerda S y una cuerda T. Diseñe un algoritmo que pueda averiguarlo a partir de la cadena S dentro de O (n) complejidad de tiempo: la subcadena más pequeña que contiene todos los caracteres de T.
Ejemplo:
输入:S = "ADOBECODEBANC", T = "ABC"
输出:"BANC"
rápido:
如果 S 中不存这样的子串,则返回空字符串 ""。
如果 S 中存在这样的子串,我们保证它是唯一的答案。
Ideas
El método de ventana deslizante: primero expanda hi para incluir T y luego aumente lo para minimizarla hasta que no cumpla con los requisitos. Continuar con el bucle para expandir hola
//初步思路
int lo=0,hi=0;//左右指针,指向最小覆盖子串的首尾
int result=0;
while(hi<N)
{
while([lo,hi]区间包含T)
{
result=max(result,hi-lo+1);
++lo;//增加lo
}
++hi;//扩大hi
}
La clave es cómo juzgar: el intervalo [lo, hi] contiene T
Puede hacer que el mapa almacene los caracteres en T y el número de ocurrencias. Si aparecen caracteres en T en el bucle, se agregan a la ventana
Use un valor para determinar la coincidencia entre el mapa y los personajes en Windows (si un personaje aparece la misma cantidad de veces, coincidirá)
int lo=0,hi=0;//左右指针,指向最小覆盖子串的首尾
int match=0;//匹配情况
for ch in T:
map.put(ch,map.get(ch)+1)
while(hi<N)
{
char ch=T[hi]
if(map.contains(ch))
{
window.put(ch,window.get(ch)+1);
if(map.get(ch)==window.get(ch)) ++match; //windows中该字符太多不会匹配多次
}
//说明至少包含了T所有字符
while(match==map.size())
{
result=max(result,hi-lo+1);
if(map.contains(T[lo])) //说明滑动了一个T中字符
{
window.put(T[lo],window.get(T[lo])-1);//look ch代表的是T[hi]
if(map.get(T[lo])>window.get(T[lo])) --match;
}
++lo;//增加lo
}
++hi;//扩大hi
}
Código
public String minWindow(String s, String t)
{
int lo=0,hi=0;//左右指针,指向最小覆盖子串的首尾
int start=0,length=Integer.MAX_VALUE;//look 记录结果 求最小,length应该为最大
int match = 0;//匹配情况
Map<Character, Integer> map = new HashMap<>();
Map<Character, Integer> window = new HashMap<>();//代表滑动窗口
for (char ch : t.toCharArray())
{
map.put(ch, map.getOrDefault(ch, 0) + 1);
}
while(hi<s.length())
{
char chHi = s.charAt(hi);//look 命名为ch可能导致下面误导用ch表示S[lo]
if(map.containsKey(chHi)) //如果出现了T中字符,则放入
{
window.put(chHi, window.getOrDefault(chHi, 0) + 1);
if(map.get(chHi).equals(window.get(chHi))) ++match; //windows中该字符太多不会匹配多次
}
while(match==map.size())
{
if(length>hi-lo+1)
{
length = hi - lo + 1;
start = lo;
}
char chLo = s.charAt(lo);
if(map.containsKey(chLo)) //说明滑动了一个T中字符
{
window.put(chLo,window.get(chLo)-1);
if(map.get(chLo)>window.get(chLo)) --match;
}
++lo;//增加lo
}
++hi;//扩大hi
}
//如果不包含这样的子串,那length没变
if(length==Integer.MAX_VALUE) return "";
return s.substring(start,start+length);
}