1. 程式人生 > >與所有單詞相關聯的字串

與所有單詞相關聯的字串

給定一個字串 s 和一些長度相同的單詞 words。在 s 中找出可以恰好串聯 words 中所有單詞的子串的起始位置。

注意子串要與 words 中的單詞完全匹配,中間不能有其他字元,但不需要考慮 words 中單詞串聯的順序。

示例 1:

輸入: s = “barfoothefoobarman”, words = [“foo”,“bar”] 輸出: [0,9] 解釋: 從索引 0 和 9 開始的子串分別是 “barfoor” 和 “foobar” 。 輸出的順序不重要, [9,0] 也是有效答案。 示例 2:

輸入: s = “wordgoodstudentgoodword”, words = [“word”,“student”] 輸出: []

(1) 方法:雜湊表匹配法 思路: 1,首先單詞長度len相同,words陣列共有num個,所以單片語成的字串為len * num; 2,先用一個雜湊表count把陣列的所有單詞和出現的次數存放起來; 3,從給的字串的開始位置i=0開始便利,取連續num * len長度字元子串,每取一個len長度子串,就去匹配 在count是否存在,如果存在,就用新的雜湊表temp將該字元子串和出現的次數存放,如果連續取得num個len長度的字元子串,並且完全匹配count雜湊表,那麼說明符合要求,則將此時的i存到結果list中; 4,i的最大值是給的字串的長度n - num * len ,在大則會餘下的字串長度已經比單片語成的字串長度小了; 5,每次取len長度的字元子串,若有一次不匹配或者出現次數已經超過了count中的次數,那麼直接跳過此次迴圈即可,否則滿足條件繼續迴圈;

核心:看程式碼,基本每一步都寫了註釋,看看分析一下就懂了!

class Solution {
public static List<Integer> findSubstring(String s, String[] words) {
   List<Integer> res = new ArrayList<>();//結果
    if (words.length == 0) //特殊情況
        return res;
    Map<String,Integer> map = new HashMap<>();//記錄陣列中每個單詞出現次數
    for (String word : words) {
        map.put(word,map.getOrDefault(word, 0) + 1);//有則加一,無則為1
    }
    int n = s.length(), num = words.length, len = words[0].length();//長度相同的單詞
    for (int i = 0; i <= n - num * len ; i ++) {//從i=0,開始位置遍歷,到餘下的字串長度已經小於給的單片語成的長度
        Map<String,Integer> temp = new HashMap<>();//存放臨時滿足的結果
        int j = 0;
        while (j < num) {//連續num個len長度的單片語成
            String word = s.substring(i + j * len, i + (j + 1)*len);//取的連續num*len長度的子字串
            if (map.containsKey(word)) {//存在要求的map中
                temp.put(word, temp.getOrDefault(word, 0) + 1);
                if (temp.get(word) > map.get(word))//數量多的情況
                    break;
            } else {
                break;
            }
            j ++;//滿足條件就繼續取下一個字元
        }
        if (j == num)//完全匹配要求
            res.add(i);
    }
    return res;
}
}
注意:對特殊情況的判斷!