题目:给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。
滑动窗口特点:
建立左右指针,先移动右指针,再移动左指针。
解题思路:
1.建立左右指针,字符串用哈希表存储
2.先滑动右指针,直到满足sMap满足tMap,再移动左指针,使得字符串长度最小
3.当左指针右移不满足tMap时,继续移动右指针
使用的结构:
哈希表,迭代器;
(当然也可以用int数组代替,利用ASCII表 )
代码如下:
import java.util.Map;
import java.util.HashMap; //哈希表
import java.util.Scanner;
import java.util.Iterator; //迭代器
public class Main {
static Map<Character,Integer> ms= new HashMap<Character,Integer>();
static Map<Character,Integer> mt= new HashMap<Character,Integer>();
public static void main(String[] args) {
Scanner in = new Scanner (System.in);
String s=in.next(); String t=in.next();
//因为该字符串有重复数字 所以不能直接put() //mt.put(t.charAt(i), i);
for(int i=0;i<t.length();i++)
mt.put(t.charAt(i), mt.getOrDefault(t.charAt(i),0)+1);
int l=0, r=-1, kl=0, kr=0;
//表示is的开头位置和结尾位置
int len=Integer.MAX_VALUE;
int slen=s.length();
int tloc=0;
while(r<slen)
{
r++;
if(r<slen&&mt.containsKey(s.charAt(r))) //s(r)出现在t中
ms.put(s.charAt(r), ms.getOrDefault(s.charAt(r),0)+1);
//ms哈希表存入该字符
while(check()&&l<=r)
{
if(r-l+1<len)
{
len=r-l+1;
kl=l; kr=l+len;
}
if(mt.containsKey(s.charAt(l))) //如果左指针出现在t中
ms.put(s.charAt(l), ms.getOrDefault(s.charAt(l),0)-1);
//因为左指针要右移, 所以ms中要减去一个
l++;
}
}
if(len==Integer.MAX_VALUE) //没有满足的子串
System.out.println("");
else
{
String s0=s.substring(kl, kr);
System.out.println(s0);
}
}
static boolean check()
{ //迭代器
Iterator it=mt.entrySet().iterator();
while(it.hasNext())
{
Map.Entry entry =(Map.Entry)it.next();
Character key=(Character) entry.getKey();
Integer val = (Integer) entry.getValue();
//如果ms中的某个字符少于mt或不存在,比对失败
if(ms.getOrDefault(key, 0)<val)
return false;
}
return true;
}
}
难点:
- Map.getOrDefault(Object key, V defaultValue)方法:
当Map中有这个key时,就使用原来的value; 没有就使用该默认值defaultValue
(参考:https://blog.csdn.net/weixin_43263961/article/details/86513880)
- 迭代器(Iterator)
Iterator it = map.entrySet().iterator();
it.next(): 返回序列中的下一个元素(首次使用返回第一个元素)
it.hasNext(): 判断序列中是否还有元素
(参考:①https://www.cnblogs.com/zzzzw/p/4945915.html
②https://www.cnblogs.com/lxqiaoyixuan/p/7156944.html)