Substring with Concatenation of All Words@LeetCode

Substring with Concatenation of All Wordsjava

比較複雜的一題,首先是要明確用滑塊的概念來解決,始終保持L集合中的字符串在滑塊中都只出現了一次,固然設置一個總計數count,當cout等於L集合長度時,即便找了一段符合要求的字符串。數組

須要用到的內存空間:code

  • 兩張哈希表,一張保存L集合中的單詞,一張用來保存當前滑塊中的單詞,key爲單詞,value爲出現次數
  • cout計數,保存當前滑塊中的單詞總數
  • left標記,記錄滑塊左起點

實現的步驟:內存

  1. 遍歷一遍單詞數組L集合,構造總單詞表
  2. 以單詞長度爲步長,遍歷目標字符串,若是當前單詞在總單詞表內,則進入步驟3;反之,則清空當前滑塊單詞表,將cout置零,將left移動到下一位置
  3. 當前滑塊檔次表中的相應單詞計數加1,檢查該單詞的計數是否小於等於總單詞表中該單詞的總數,若是是,則將count計數加1,進入步驟5;反之,進入步驟4
  4. 根據左起點left收縮滑塊,直到收縮到與當前單詞相同的字符串片斷,將其剔除以後,滑塊的收縮工做完成
  5. 若是當前count計數等於單詞集合長度,記錄下left左起點的位置後,將left右移,當前滑塊中相應單詞計數減1,總計數減1,繼續循環

這裏解釋下步驟4中的收縮滑塊,這是由於當前滑塊中有單詞的出現次數超過了額定的出現次數,那麼就是須要收縮滑塊來剔除這個單詞,至關因而從滑塊的左起點開始尋找該單詞,找到以後,將該單詞的右端點做爲滑塊新的左起點,這樣就保證了滑塊中全部單詞都是小於等於額定出現次數,這樣也保證了count計數的有效性。leetcode

遇到總單詞表中不存在的單詞的狀況,在步驟2中已經說明,清空當前數據以後繼續循環,也就是保證了滑塊中是不會出現不存在單詞表中的單詞的。字符串

最後,考慮最外圈循環,若是是從0開始做爲滑塊的初始起點,那麼其實並無遍歷字符串中的全部可能子串,由於步長是單詞長度,因此移動滑塊的時候會跨過不少可能子串,因此要在外圈再加一層循環,這個循環的做用就是移動滑塊的初始起點,因此循環次數就是單詞的長度。get

實現代碼:string

javapublic class Solution {
    public List<Integer> findSubstring(String S, String[] L) {
        ArrayList<Integer> result = new ArrayList<Integer>();
        if (S == null || S.length() == 0 || L == null || L.length == 0)
            return result;
        int strLen = S.length();
        int wordLen = L[0].length();
        HashMap<String, Integer> map = new HashMap<String, Integer>();
        for (int i = 0; i < L.length; i++) {
            if (map.containsKey(L[i])) {
                map.put(L[i], map.get(L[i]) + 1);
            } else {
                map.put(L[i], 1);
            }
        }
        for (int i = 0; i < wordLen; i++) {
            HashMap<String, Integer> curMap = new HashMap<String, Integer>();
            int count = 0, left = i;
            for (int j = i; j <= strLen - wordLen; j += wordLen) {
                String curStr = S.substring(j, j + wordLen);
                if (map.containsKey(curStr)) {
                    if (curMap.containsKey(curStr)) {
                        curMap.put(curStr, curMap.get(curStr) + 1);
                    } else {
                        curMap.put(curStr, 1);
                    }
                    if (curMap.get(curStr) <= map.get(curStr)) {
                        count++;
                    } else {
                        while (true) {
                            String tmp = S.substring(left, left + wordLen);
                            curMap.put(tmp, curMap.get(tmp) - 1);
                            left += wordLen;
                            if (curStr.equals(tmp)) {
                                break;
                            } else {
                                count--;
                            }
                        }
                    }
                    if (count == L.length) {
                        result.add(left);
                        String tmp = S.substring(left, left + wordLen);
                        curMap.put(tmp, curMap.get(tmp) - 1);
                        left += wordLen;
                        count--;
                    }
                } else {
                    curMap.clear();
                    count = 0;
                    left = j + wordLen;
                }
            }
        }
        return result;
    }
}
相關文章
相關標籤/搜索