【LeetCode】#30与所有单词相关联的字串(Substring with Concatenation of All Words)
题目描述
给定一个字符串 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”]
输出: []
Description
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.
Example
Example 1:
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.
Example 2:
Input:
s = “wordgoodstudentgoodword”,
words = [“word”,“student”]
Output: []
解法
解法1:
class Solution {
public List<Integer> findSubstring(String s, String[] words) {
List<Integer> res = new ArrayList<>();
if(s.length()==0 || words.length==0){
return res;
}
for(int i=1; i<words.length; i++){
if(words[i].length()!=words[i-1].length()){
return res;
}
}
int len = words[0].length();
int total = len * words.length;
if(s.length()<total){
return res;
}
int j = 0;
while(j+total<=s.length()){
String smallS = s.substring(j, j+total);
int k = 0;
String[] testWords = new String[words.length];
for(int i=0; i<words.length; i++){
testWords[i] = words[i];
}
for(int i=0; i<words.length; i++){
boolean flag = false;
String testS = smallS.substring(k, k+len);
for(int l=0; l<testWords.length; l++){
if(testWords[l].equals(testS)){
testWords[l] = "";
break;
}
if(l==testWords.length-1){
flag = true;
}
}
if(flag){
break;
}
if(i==words.length-1){
res.add(j);
}
k += len;
}
j++;
}
return res;
}
}
解法2:
class Solution {
public List<Integer> findSubstring(String s, String[] words) {
if(s.length()==0 || words.length==0) return new ArrayList<>();
Map<String,Integer> wordsMap=new HashMap<>();
List<Integer> ans=new ArrayList<>();
int len=words[0].length(),cnt=words.length,wordlength=len*cnt;
for (int i=0;i<words.length;i++){
wordsMap.put(words[i],wordsMap.getOrDefault(words[i],0)+1);
}
for (int i=0;i<len;i++){
for(int j=i;j+wordlength<=s.length();j+=len){
String curStr=s.substring(j,j+wordlength);
Map<String,Integer> map=new HashMap<>();
for (int k=cnt-1;k>=0;k--){
String subCurStr=curStr.substring(k*len,(k+1)*len);
int count=map.getOrDefault(subCurStr,0)+1;
if(count>wordsMap.getOrDefault(subCurStr,0)){
j=j+k*len;
break;
}
else if(k==0 && !ans.contains(j)){
ans.add(j);
}
else map.put(subCurStr,count);
}
}
}
return ans;
}
}