File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ My accepted leetcode solutions to some of the common interview problems.
206206
- [Partition Labels](problems/src/hashing/PartitionLabels.java) (Medium)
207207
- [Custom Sort String](problems/src/hashing/CustomSortString.java) (Medium)
208208
- [Short Encoding of Words](problems/src/hashing/ShortEncodingOfWords.java) (Medium)
209+
- [Substring with Concatenation of All Words](problems/src/hashing/SubstringConcatenationOfWords.java) (Hard)
209210

210211
#### [Heap](problems/src/heap)
211212

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package hashing;
2+
3+
import java.util.ArrayList;
4+
import java.util.HashMap;
5+
import java.util.List;
6+
import java.util.Map;
7+
8+
/**
9+
* Created by gouthamvidyapradhan on 02/03/2019
10+
* You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices
11+
* of substring(s) in s that is a concatenation of each word in words exactly once and without any intervening characters.
12+
*
13+
* Example 1:
14+
*
15+
* Input:
16+
* s = "barfoothefoobarman",
17+
* words = ["foo","bar"]
18+
* Output: [0,9]
19+
* Explanation: Substrings starting at index 0 and 9 are "barfoor" and "foobar" respectively.
20+
* The output order does not matter, returning [9,0] is fine too.
21+
* Example 2:
22+
*
23+
* Input:
24+
* s = "wordgoodgoodgoodbestword",
25+
* words = ["word","good","best","word"]
26+
* Output: []
27+
*
28+
* Solution:
29+
* General idea is to do the following
30+
* 1. Calculate the word count for the given array of words and store this in a HashMap.
31+
* 2. For every substring (substring of s) of length (words[0].length() * words.length) split this into words of
32+
* length words[0].length and calculate the word frequency for the split words. If the word frequency matches
33+
* the word frequency of the given original word list then add the starting index of this substring into the result
34+
* array.
35+
*
36+
* A small optimization is to break the substring match as soon as you find out that the word formed from the substring
37+
* is not part of the original given word list or if the frequency of the word exceeds the frequency of the original
38+
* word count.
39+
*/
40+
public class SubstringConcatenationOfWords {
41+
42+
/**
43+
* Main method
44+
* @param args
45+
*/
46+
public static void main(String[] args) {
47+
String[] words = {"word","good","best","word"};
48+
System.out.println(new SubstringConcatenationOfWords().findSubstring("wordgoodgoodgoodbestword", words));
49+
}
50+
51+
public List<Integer> findSubstring(String s, String[] words) {
52+
if(words.length == 0) return new ArrayList<>();
53+
int wLen = words[0].length();
54+
int sLen = wLen * words.length;
55+
List<Integer> result = new ArrayList<>();
56+
if(sLen > s.length()) return result;
57+
Map<String, Integer> countMap = new HashMap<>();
58+
for(String w : words){
59+
countMap.putIfAbsent(w, 0);
60+
countMap.put(w, countMap.get(w) + 1);
61+
}
62+
for(int k = 0; (s.length() - k) >= sLen; k++) {
63+
Map<String, Integer> subSMap = new HashMap<>();
64+
int i = k;
65+
for(int j = i + wLen; (i - k) < sLen; i = j, j += wLen){
66+
String subS = s.substring(i, j);
67+
subSMap.putIfAbsent(subS, 0);
68+
subSMap.put(subS, subSMap.get(subS) + 1);
69+
if(!countMap.containsKey(subS) || subSMap.get(subS) > countMap.get(subS)){
70+
break;
71+
}
72+
}
73+
if((i - k) >= sLen){
74+
result.add(k);
75+
}
76+
}
77+
return result;
78+
}
79+
}

0 commit comments

Comments
 (0)