Minimum Window Substring 最小覆蓋子串算法

算法 字符串 雙指針 2016-03-02

公司要出套Java面試題, 寫到算法處理字符串這段基矮,想起MWS算法,比較有代表性且數(shù)據(jù)結(jié)構(gòu)取巧冠场。
現(xiàn)在把解題思路再梳理一把家浇。

給定一個(gè)字符串S和T,在S中找到一個(gè)最小的子串包含T中的所有字符碴裙,時(shí)間復(fù)雜度為O(n)钢悲。
Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n).

舉例,
S = "ADOBECODEBANC"
T = "ABC"
最小子串是"BANC".

這里有幾個(gè)點(diǎn)需要說明下:

時(shí)間復(fù)雜度是O(n)

其中n是字符串S的長度灌具,因?yàn)槊總€(gè)字符在維護(hù)窗口的過程中不會(huì)被訪問多于兩次。

空間復(fù)雜度則是O(1)

也就是代碼中T的長度譬巫。

數(shù)據(jù)結(jié)構(gòu)選擇

記錄字母出現(xiàn)次數(shù)的數(shù)據(jù)結(jié)構(gòu)有采用哈希Map的也有采用數(shù)組的咖楣,這里介紹一下數(shù)組的用法,因?yàn)樗昧吮容^取巧的方式芦昔。
大小寫字母的ASCII碼不大于128诱贿,這樣array['A']=3指A出現(xiàn)3次,array['B']=1指B出現(xiàn)了一次咕缎,以此類推珠十,不能用常規(guī)意義上的定義array[0]=3表示A出現(xiàn)3次,這樣就多了一層映射凭豪!故而數(shù)組的長度設(shè)置為128即可存放所有的字母焙蹭。明白了么?

算法思想

  1. 首先預(yù)處理T嫂伞,用一個(gè)128長 (示例代碼用了256) 的整數(shù)數(shù)組srcHash存儲(chǔ)里面每個(gè)目標(biāo)字符出現(xiàn)的個(gè)數(shù)
  2. 然后處理原串S孔厉,也用一個(gè)128長的整數(shù)數(shù)組destHash記錄原串字符出現(xiàn)的個(gè)數(shù)。給定兩個(gè)指針start和end帖努,作為最小窗口的左右邊界撰豺。具體實(shí)現(xiàn)看下代碼一目了然。
    public class Solution {
        public String minWindow(String S, String T) {
            int[] srcHash = new int[255];
            // 記錄目標(biāo)字符串每個(gè)字母出現(xiàn)次數(shù)
            for(int i = 0; i < T.length(); i++){
                srcHash[T.charAt(i)]++;
            }
            int start = 0,i= 0;
            // 用于記錄窗口內(nèi)每個(gè)字母出現(xiàn)次數(shù) 
            int[] destHash = new int[255];
            int found = 0;
            int begin = -1, end = S.length(), minLength = S.length();
            for(start = i = 0; i < S.length(); i++){
                // 每來一個(gè)字符給它的出現(xiàn)次數(shù)加1
                destHash[S.charAt(i)]++;
                // 如果加1后這個(gè)字符的數(shù)量不超過目標(biāo)串中該字符的數(shù)量拼余,則找到了一個(gè)匹配字符
                if(destHash[S.charAt(i)] <= srcHash[S.charAt(i)]) found++;
                // 如果找到的匹配字符數(shù)等于目標(biāo)串長度污桦,說明找到了一個(gè)符合要求的子串    
                if(found == T.length()){
                    // 將開頭沒用的都跳過,沒用是指該字符出現(xiàn)次數(shù)超過了目標(biāo)串中出現(xiàn)的次數(shù)匙监,并把它們出現(xiàn)次數(shù)都減1
                    while(start < i && destHash[S.charAt(start)] > srcHash[S.charAt(start)]){
                        destHash[S.charAt(start)]--;
                        start++;
                    }
                    // 這時(shí)候start指向該子串開頭的字母凡橱,判斷該子串長度
                    if(i - start < minLength){
                        minLength = i - start;
                        begin = start;
                        end = i;
                    }
                    // 把開頭的這個(gè)匹配字符跳過,并將匹配字符數(shù)減1
                    destHash[S.charAt(start)]--;
                    found--;
                    // 子串起始位置加1亭姥,我們開始看下一個(gè)子串了
                    start++;
                }
            }
            // 如果begin沒有修改過稼钩,返回空
            return begin == -1 ? "" : S.substring(begin,end + 1);
        }
    }

加深理解:

解題思路其實(shí)就是通過雙指針維持一個(gè)Window,窗口右指針向右擴(kuò)張用來找到包含子串為目的致份,窗口左指針向右收縮以使子串最小变抽。
典型的滑動(dòng)窗口方法的實(shí)現(xiàn)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末氮块,一起剝皮案震驚了整個(gè)濱河市绍载,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌滔蝉,老刑警劉巖击儡,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蝠引,死亡現(xiàn)場離奇詭異,居然都是意外死亡鸽疾,警方通過查閱死者的電腦和手機(jī)训貌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進(jìn)店門豺鼻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來儒飒,“玉大人檩奠,你說我怎么就攤上這事笆凌。” “怎么了?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵爪模,是天一觀的道長屋灌。 經(jīng)常有香客問我共郭,道長除嘹,這世上最難降的妖魔是什么尉咕? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任年缎,我火速辦了婚禮单芜,結(jié)果婚禮上洲鸠,老公的妹妹穿的比我還像新娘坛怪。我一直安慰自己更啄,他們只是感情好祭务,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布怪嫌。 她就那樣靜靜地躺著义锥,像睡著了一般。 火紅的嫁衣襯著肌膚如雪岩灭。 梳的紋絲不亂的頭發(fā)上拌倍,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天,我揣著相機(jī)與錄音噪径,去河邊找鬼柱恤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛找爱,可吹牛的內(nèi)容都是我干的梗顺。 我是一名探鬼主播,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼车摄,長吁一口氣:“原來是場噩夢啊……” “哼寺谤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起吮播,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤变屁,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后薄料,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體敞贡,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年摄职,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了誊役。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片获列。...
    茶點(diǎn)故事閱讀 39,991評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蛔垢,靈堂內(nèi)的尸體忽然破棺而出击孩,到底是詐尸還是另有隱情,我是刑警寧澤鹏漆,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站艺玲,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏饭聚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一秒梳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧朋譬,春花似錦、人聲如沸兴垦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至扶关,卻和暖如春数冬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背拐纱。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留秸架,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓东抹,卻偏偏與公主長得像沃测,于是被迫代替她去往敵國和親食茎。 傳聞我的和親對象是個(gè)殘疾皇子蒂破,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評論 2 355

推薦閱讀更多精彩內(nèi)容