與所有單詞相關聯的字串
阿新 • • 發佈:2018-12-16
給定一個字串 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; } } 注意:對特殊情況的判斷!