菜鸡每日一题系列打卡76天
每天一道算法题目
小伙伴们一起留言打卡
坚持就是胜利,我们一起努力!
题目描述(引自LeetCode)
给你一个字符串S、一个字符串T,请在字符串S里面找出:包含T所有字符的最小子串。
示例:
输入: S = "ADOBECODEBANC", T = "ABC"
输出: "BANC"
说明:
如果S中不存这样的子串,则返回空字符串""。
如果S中存在这样的子串,我们保证它是唯一的答案。
题目分析
本题是一道寻找字符串符合要求的子串的题目。容易想到的是,先在S中找到包含T所有字符的子串,然后再找到最小子串。这一过程可以利用滑动窗口进行实现。
经过在LeetCode平台的一番测试之后,菜鸡发现了两个现象:
T中的字符有可能重复
测试用例中S与T均由大小写字母组成
这两点很关键,菜鸡将以这两点为前提,进行解答。
代码实现
class Solution {
public String minWindow(String s, String t) {
// 特殊情况判断
if (s == null || t == null || s.length() < t.length()) return "";
// 准备
int start = 0, end = 0, count = 0;
int minStart = -1, minEnd = -1, minLength = s.length() + 1;
int[] tArray = new int[58], tmp = new int[58];
for (int i = 0; i < t.length(); i++) tArray[t.charAt(i) - 65]++;
// 滑动窗口
while (end < s.length()) {
int index = s.charAt(end) - 65;
if (tArray[index] >= ++tmp[index]) count++;
while (count == t.length()) {
index = s.charAt(start) - 65;
if (tArray[index] >= tmp[index]--) {
count--;
if (end - start + 1 < minLength) {
minLength = end - start + 1;
minStart = start;
minEnd = end;
}
}
start++;
}
end++;
}
// 返回结果
return minStart == -1 ? "" : s.substring(minStart, minEnd + 1);
}
}
代码分析
再次强调,本解答是基于S与T均由大小写字母组成的前提下实现的,如果字符集有变化,则需要相应地增大数组长度,也可以用map进行实现。
对代码进行分析,不妨设S长度为m,T长度为n,字符集大小为c,则时间复杂度为O(cm + n)。一般情况下,n < m,c可以认为是某种程度的常数,因此,时间复杂度可以看作O(m)。
而就空间而言,空间复杂度为O(c),c可以认为是某种程度的常数,因此,空间复杂度可以看作O(1)。
执行结果


学习 | 工作 | 分享

????长按关注“有理想的菜鸡”
只有你想不到,没有你学不到
593

被折叠的 条评论
为什么被折叠?



