菜雞每日一題系列打卡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)。
執行結果
學習 | 工作 | 分享
????長按關注“有理想的菜雞”
只有你想不到,沒有你學不到