Design
, Hash Map
Medium
Design a class which receives a list of words in the constructor, and implements a method that takes two words _word1 _and _word2 _and return the shortest distance between these two words in the list. Your method will be called _repeatedly _many times with different parameters.
Example:
Assume that words =["practice", "makes", "perfect", "coding", "makes"]
.
Copy Input:
word1
=
“coding”
,
word2
=
“practice”
Output:
3
Copy Input:
word1
=
"makes"
,
word2
=
"coding"
Output:
1
Note:
You may assume thatword1 does not equal to word2 , and _word1 _and _word2 _are both in the list.
Analysis
顺序遍历words[],把对应index放入hashmap中<String, ArrayList<Integer>>;这样每个word对应的index其实是默认按照升序排好序了。
shortest()在计算时,brute-force就是两重循环找min。但是更聪明的办法是用two pointers,分别在两个sorted list中,最小的绝对值之差就可以通过一重循环找到了。
Copy list1.get(i1) < list2.get(i2) 则增加i1,否则增加i2
Solution
Location mapping, and brute force two nested for loops
shortest() takes O(pq)
time
Copy class WordDistance {
private HashMap<String, ArrayList<Integer>> map;
public WordDistance(String[] words) {
map = new HashMap<>();
for (int i = 0; i < words.length; i++) {
if (!map.containsKey(words[i])) {
map.put(words[i], new ArrayList<Integer>());
}
map.get(words[i]).add(i);
}
}
public int shortest(String word1, String word2) {
List<Integer> p1 = map.get(word1);
List<Integer> p2 = map.get(word2);
if (p1 == null || p2 == null) {
return -1;
}
int shortest = Integer.MAX_VALUE;
for (Integer i1: p1) {
for (Integer i2: p2) {
shortest = Math.min(Math.abs(i1 - i2), shortest);
}
}
return shortest;
}
}
/**
* Your WordDistance object will be instantiated and called as such:
* WordDistance obj = new WordDistance(words);
* int param_1 = obj.shortest(word1,word2);
*/
Optimized - using two pointers
shortest() takes O(p + q)
time
Copy class WordDistance {
private HashMap<String, ArrayList<Integer>> map;
public WordDistance(String[] words) {
map = new HashMap<>();
for (int i = 0; i < words.length; i++) {
if (!map.containsKey(words[i])) {
map.put(words[i], new ArrayList<Integer>());
}
map.get(words[i]).add(i);
}
}
public int shortest(String word1, String word2) {
List<Integer> p1 = map.get(word1);
List<Integer> p2 = map.get(word2);
if (p1 == null || p2 == null) {
return -1;
}
int shortest = Integer.MAX_VALUE;
int i1 = 0;
int i2 = 0;
while (i1 < p1.size() && i2 < p2.size()) {
shortest = Math.min(Math.abs(p1.get(i1) - p2.get(i2)), shortest);
if (p1.get(i1) < p2.get(i2)) {
i1++;
} else {
i2++;
}
}
return shortest;
}
}
/**
* Your WordDistance object will be instantiated and called as such:
* WordDistance obj = new WordDistance(words);
* int param_1 = obj.shortest(word1,word2);
*/
Reference
https://leetcode.com/problems/shortest-word-distance-ii/solution/