每日一題——最小覆蓋子串

菜雞每日一題系列打卡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)。

執行結果

學習 | 工作 | 分享

????長按關注“有理想的菜雞

只有你想不到,沒有你學不到

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章