76.最小覆盖子串
给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字母的最小子串。
示例:
输入: S = “ADOBECODEBANC”, T = “ABC”
输出: “BANC”
说明:
如果 S 中不存这样的子串,则返回空字符串 “”。
如果 S 中存在这样的子串,我们保证它是唯一的答案。
思路
这题目说实话有点小难啊,因为要处理字符串,我写的是大量的字符串删除操作、拼接操作,运行速度太慢了,以至于无法通过最后一个测试用例。。。最后一个用例属实恶心,一共10004个字符,先跳过它吧,记录下解题思路。
特点:首先我们可以发现输出串有一个特点,他的首尾字符必然是目标串T中的。
算法模板如下:
从S的首字符往后检索
if 当前字符在串T中
{
删除T中的这个字符
if 串T的长度为0
{
记录当前遍历串的起始位置和结束位置
比较记录的长度是不是最短
break;
}
从当前位置向后继续遍历串S
if 当前字符在串T中
{
删除这个字符
if 串T的长度为0
{
记录当前遍历串的起始位置和结束位置
比较记录的长度是不是最短
break;
}
}
}
这里删除串中的一个字符在java的库函数里面没有找到对应的函数,于是自己实现了一个:
public static String removeCharAt(String s, int pos) {
if(pos == s.length() - 1)
return s.substring(0, pos);
else
return s.substring(0, pos) + s.substring(pos + 1);
}
- 这样会造成大量的字符串拼接,速度极慢。
- 判断字符是不是在串中使用了函数indexof,这每次都需要从头往后遍历字符串,而不如哈希表那样查找键值来的快。
哈希表是直接通过哈希值计算出键值位置的,在查找速度上快了很多倍,感觉哈希表查找元素就和数组查找第几项这样,有一个公式可以直接访问到哪一项的内存,然后indexof函数查找第几项就像链表一样需要从头往后检索。
代码实现
class Solution {
public String minWindow(String s, String t) {
if(t.length() > s.length())
return "";
if(t.equals(s))
return t;
int minLength = 1000000;
int start = 0,end = 0;
for(int i = 0; i < s.length();)
{
int first_index = -1;
int indexOft = t.indexOf(s.charAt(i));
if(indexOft != -1)
{
String t_temp = removeCharAt(t, indexOft);
if(t_temp.length() == 0)
{
minLength = 1;
start = i;
end = i;
break;
}
for(int j = i + 1; j < s.length(); j++)
{
indexOft = t_temp.indexOf(s.charAt(j));
if(first_index == -1 && t.indexOf(s.charAt(j)) != -1)
{
first_index = j;//下次从这开始
}
if(indexOft != -1)
{
t_temp = removeCharAt(t_temp, indexOft);
if(t_temp.length() == 0)
{
if(j - i < minLength)
{
minLength = j - i;
start = i;
end = j;
}
break;
}
}
}
}
if(first_index != -1)
i = first_index;//从记录位置开始
else
i++;
}
if(minLength == 1000000)
return "";
else
return s.substring(start,end + 1);
}
public static String removeCharAt(String s, int pos) {
if(pos == s.length() - 1)
return s.substring(0, pos);
else
return s.substring(0, pos) + s.substring(pos + 1);
}
}
哎,写的属实太乱了一点都不美观,可以之后尝试下使用HashMap来解决这个问题,我这应该也算是使用了滑动窗口的算法思想吧。