[LeetCode] 30. Substring with Concatenation of All Words

You are given a string s and an array of strings words of the same length. Return all starting indices of substring(s) in s that is a concatenation of each word in words exactly once, in any order, and without any intervening characters.

You can return the answer in any order.

Example 1:

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

Example 2:

Input: s = "wordgoodgoodgoodbestword", words = ["word","good","best","word"]
Output: []

Example 3:

Input: s = "barfoofoobarthefoobarman", words = ["bar","foo","the"]
Output: [6,9,12]

Constraints:

  • 1 <= s.length <= 104
  • s consists of lower-case English letters.
  • 1 <= words.length <= 5000
  • 1 <= words[i].length <= 30
  • words[i] consists of lower-case English letters.

串联所有单词的子串。

给定一个字符串 s 和一些 长度相同 的单词 words 。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。

注意子串要与 words 中的单词完全匹配,中间不能有其他字符 ,但不需要考虑 words 中单词串联的顺序。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/substring-with-concatenation-of-all-words
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路是滑动窗口(sliding window),但是没法套用之前的模板。注意这个题给的条件,words 里面每个单词是等长的,这个条件会使得这个题目简单些。首先创建一个 hashmap 把 words 里面的所有单词和出现次数都记录下来。接着开始遍历字符串 s,每移动一个字符,就要复制一次之前的 hashmap,因为这里的思路是需要看从起点 i 开始的 substring 是否包含 hashmap 里面存的所有单词(及其次数)。当找到一个子串的时候,需要判断这个子串是否还在 hashmap 里,如果这个子串不存在或者次数已经为 0 了则 break,说明以当前 i 为起点的子串无效;如果这个子串存在于 hashmap 则--,同时 words 的个数 K 也要--,这样当 K == 0 的时候就可以知道所有单词都遍历完了,可以把这个子串的起始位置 i 加入结果集了。

时间O(n^2)

空间O(n)

Java实现

 1 class Solution {
 2     public List<Integer> findSubstring(String s, String[] words) {
 3         List<Integer> res = new ArrayList<>();
 4         // corner case
 5         if (s == null || words == null || words.length == 0) {
 6             return res;
 7         }
 8 
 9         // normal case
10         // 单词个数
11         int n = words.length;
12         // 单词长度
13         int m = words[0].length();
14         HashMap<String, Integer> map = new HashMap<>();
15         for (String str : words) {
16             map.put(str, map.getOrDefault(str, 0) + 1);
17         }
18 
19         for (int i = 0; i <= s.length() - n * m; i++) {
20             HashMap<String, Integer> copy = new HashMap<>(map);
21             int count = n;
22             int j = i;
23             while (count > 0) {
24                 String str = s.substring(j, j + m);
25                 if (!copy.containsKey(str) || copy.get(str) < 1) {
26                     break;
27                 }
28                 copy.put(str, copy.get(str) - 1);
29                 count--;
30                 j += m;
31             }
32             if (count == 0) {
33                 res.add(i);
34             }
35         }
36         return res;
37     }
38 }

 

JavaScript实现

 1 /**
 2  * @param {string} s
 3  * @param {string[]} words
 4  * @return {number[]}
 5  */
 6 var findSubstring = function (s, words) {
 7     // corner case
 8     if (s == null || words == null || words.length == 0) {
 9         return [];
10     }
11 
12     // normal case
13     let res = [];
14     let n = words.length;
15     let m = words[0].length;
16     let map = {};
17     for (let str of words) {
18         map[str] = (map[str] || 0) + 1;
19     }
20 
21     for (let i = 0; i <= s.length - n * m; i++) {
22         let copy = { ...map };
23         let k = n;
24         let j = i;
25         while (k > 0) {
26             let str = s.substring(j, j + m);
27             if (!copy[str] || copy[str] < 1) {
28                 break;
29             }
30             copy[str]--;
31             k--;
32             j += m;
33         }
34         if (k == 0) {
35             res.push(i);
36         }
37     }
38     return res;
39 };

 

sliding window相关题目

LeetCode 题目总结

posted @ 2020-04-04 08:01  CNoodle  阅读(416)  评论(0编辑  收藏  举报