LeetCode代碼分析——30. Substring with Concatenation of All Words(理解滑動窗口)

題目描述

You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without any intervening characters.
給定一個(gè)String s和一個(gè)單詞的數(shù)組words上渴,數(shù)組里面的單詞長度相等榛瓮,從s中找出字符串缝呕,使得數(shù)組中的每個(gè)單詞剛好都出現(xiàn)過一次,也就是字符串是數(shù)組中單詞的一個(gè)全排列撞秋。

Example
Input:
s = "barfoothefoobarman",
words = ["foo","bar"]
Output: [0,9]
Explanation: Substrings starting at index 0 and 9 are "barfoor" and "foobar" respectively.
The output order does not matter, returning [9,0] is fine too.

思路分析

注意題目中的條件绸硕,words數(shù)組中的單詞長度相等琼讽,如果沒有這個(gè)條件這道題還挺復(fù)雜的徘熔。如果長度相等的話形如barfoofoothefoobarman的字符串就可以被三等分

  • bar foo foo the foo bar man
  • b arf oof oot hef oob arm an
  • ba rfo ofo oth efo oba rma n

三個(gè)為一組進(jìn)行分組,總共三種可能的分組霉猛。同時(shí)注意條件尺锚,words數(shù)組中的單詞可以重復(fù),會出現(xiàn)["foo","bar","foo"]的情況惜浅,這種情況也需要匹配到兩個(gè)foo瘫辩,即foobarfoo這樣的子串。
因此需要先用一個(gè)Map wordMap來記錄下words數(shù)組中每個(gè)單詞的次數(shù)赡矢,例如本例中就是
bar: 1
foo: 1
然后分別對以上三種分組方式進(jìn)行分析杭朱,遍歷采用left和right兩個(gè)指針,對s中的每個(gè)單詞和words數(shù)組中的進(jìn)行匹配吹散,同時(shí)用tempMap記錄當(dāng)前l(fā)eft和right指針之間的各個(gè)單詞的數(shù)量(用來和wordMap比較)弧械。
算法的執(zhí)行過程如圖。

算法執(zhí)行邏輯

left和right指針組成了一個(gè)滑動窗口空民,通過tempMap 忠實(shí)記錄left和right指針之間的單詞匹配計(jì)數(shù)(只要left right指針發(fā)生移動就立刻更新)刃唐,在發(fā)現(xiàn)某個(gè)單詞(如foo)超過了模板wordMap中的計(jì)數(shù),則滑動窗口左邊界逐漸右移界轩,同時(shí)更新tempMap画饥,直到多余的foo被彈了出去,再繼續(xù)右移右指針進(jìn)行操作浊猾。
核心在于理解為什么要用滑動窗口抖甘,本題是通過滑動窗口+記錄用的Map來保證窗口內(nèi)的單詞數(shù)和要求的個(gè)數(shù)統(tǒng)一。(有些類似于網(wǎng)絡(luò)的滑動窗口協(xié)議葫慎,為了保持幀的傳輸順序和傳輸個(gè)數(shù)衔彻,也是說在窗口里的一定要是要求的結(jié)果的子集薇宠,窗口里不允許進(jìn)入不符合要求的元素)

代碼實(shí)現(xiàn)

class Solution {
    public List<Integer> findSubstring(String s, String[] words) {
               List<Integer> result = new ArrayList<>();
        Map<String, Integer> wordMap = new HashMap<>();
        for (String word : words) {
            if (wordMap.containsKey(word)) {
                wordMap.put(word, wordMap.get(word) + 1);
            } else {
                wordMap.put(word, 1);
            }
        }

        if (s.length() == 0 || words.length == 0) {
            return result;
        }

        int wordLen = words[0].length();
        int totalLen = wordLen * words.length;

        for (int i = 0; i < words[0].length(); i++) {
            int left = i;
            int right = i;
            Map<String, Integer> tempMap = new HashMap<>();
            while (right + wordLen <= s.length()) {
                // 滑窗右側(cè)擴(kuò)張
                String temp = s.substring(right, right + wordLen);
                right += wordLen;
                if (wordMap.containsKey(temp)) {
                    if (tempMap.containsKey(temp)) {
                        tempMap.put(temp, tempMap.get(temp) + 1);
                    } else {
                        tempMap.put(temp, 1);
                    }
                    while (tempMap.get(temp) > wordMap.get(temp)) {
                        // temp單詞匹配過多,滑窗左邊逐漸縮小艰额,直到彈出多余的單詞
                        String leftStr = s.substring(left, left + wordLen);
                        tempMap.put(leftStr, tempMap.get(leftStr) - 1);
                        left += wordLen;
                    }
                    if (right - left == totalLen) {
                        // 通過滑窗大小來判斷是否匹配成功
                        result.add(left);
                    }
                } else {
                    // 沒有匹配到澄港,滑窗縮小為0,從right部分重新開始
                    tempMap = new HashMap<>();
                    left = right;
                }
            }
        }

        return result;
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末柄沮,一起剝皮案震驚了整個(gè)濱河市回梧,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌祖搓,老刑警劉巖狱意,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異棕硫,居然都是意外死亡髓涯,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進(jìn)店門哈扮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蚓再,你說我怎么就攤上這事滑肉。” “怎么了摘仅?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵靶庙,是天一觀的道長。 經(jīng)常有香客問我娃属,道長六荒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任矾端,我火速辦了婚禮掏击,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘秩铆。我一直安慰自己砚亭,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布殴玛。 她就那樣靜靜地躺著捅膘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪滚粟。 梳的紋絲不亂的頭發(fā)上寻仗,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天,我揣著相機(jī)與錄音凡壤,去河邊找鬼署尤。 笑死蔬咬,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的沐寺。 我是一名探鬼主播林艘,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼混坞!你這毒婦竟也來了狐援?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤究孕,失蹤者是張志新(化名)和其女友劉穎啥酱,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體厨诸,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡镶殷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了微酬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片绘趋。...
    茶點(diǎn)故事閱讀 39,981評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖颗管,靈堂內(nèi)的尸體忽然破棺而出陷遮,到底是詐尸還是另有隱情,我是刑警寧澤垦江,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布帽馋,位于F島的核電站,受9級特大地震影響比吭,放射性物質(zhì)發(fā)生泄漏绽族。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一衩藤、第九天 我趴在偏房一處隱蔽的房頂上張望吧慢。 院中可真熱鬧,春花似錦慷彤、人聲如沸娄蔼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽岁诉。三九已至,卻和暖如春跋选,著一層夾襖步出監(jiān)牢的瞬間涕癣,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留坠韩,地道東北人距潘。 一個(gè)月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像只搁,于是被迫代替她去往敵國和親音比。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評論 2 355

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