LeetCode – Shortest Word Distance II (Java)

This is a follow up of Shortest Word Distance. The only difference is now you are given the list of words and your method will be called repeatedly many times with different parameters. How would you optimize it?

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.

For example,
Assume that words = ["practice", "makes", "perfect", "coding", "makes"].

Given word1 = “coding”, word2 = “practice”, return 3.
Given word1 = "makes", word2 = "coding", return 1.

Java Solution

public class WordDistance {
    HashMap<String, ArrayList<Integer>> map;
    public WordDistance(String[] words) {
        map = new HashMap<String, ArrayList<Integer>>();
        for(int i=0; i<words.length; i++){
            if(map.containsKey(words[i])){
                map.get(words[i]).add(i);
            }else{
                ArrayList<Integer> list = new ArrayList<Integer>();
                list.add(i);
                map.put(words[i], list);
            }
        }
    }
 
    public int shortest(String word1, String word2) {
 
        ArrayList<Integer> l1 = map.get(word1);
        ArrayList<Integer> l2 = map.get(word2);
 
        int result = Integer.MAX_VALUE;
        for(int i1: l1){
            for(int i2: l2){
                result = Math.min(result, Math.abs(i1-i2));
            }
        }
        return result;
    }
}

The time complexity for shortest method is O(M*N), where M is freqency of word1 and N is the frequency of word2. This can be improved by the following:

public int shortest(String word1, String word2) {
 
    ArrayList<Integer> l1 = map.get(word1);
    ArrayList<Integer> l2 = map.get(word2);
 
    int result = Integer.MAX_VALUE;
    int i=0; 
    int j=0;
    while(i<l1.size() && j<l2.size()){
        result = Math.min(result, Math.abs(l1.get(i)-l2.get(j)));
        if(l1.get(i)<l2.get(j)){
            i++;
        }else{
            j++;
        }     
    }
 
    return result;
}

The time complexity of the shortest method is now O(M+N). Since M+N < size of word list, the time is O(K) where k is the list size.

Category >> Algorithms  
If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
<pre><code> 
String foo = "bar";
</code></pre>
  • p.andrey

    My mistake… sorry. the square complexity is for the naive version (the one with two loops), even so my comment is wrong, you are right: n and m are frequencies.

  • Bonsai

    I don’t get wha you mean by “Assume len(n)>=len(m), then we can say that the time complexity is O(n^2) and respectively O(n).”. The improved shortest method time is O(n), right?

  • p.andrey

    If len(word1)=n and len(word2)=m, then the naive version has time complexity O(n*m) and the improved version has the time complexity O(n+m). Assume len(n)>=len(m), then we can say that the time complexity is O(n^2) and respectively O(n).

  • Harshit Singh

    Tried this, working for this particular example.
    Tell me if I got the question wrong.

    String word1="makes",word2="coding";
    String dict[]={"practice", "makes", "perfect", "coding", "makes"};

    int pos1=-1,pos2=-1;
    int mindist=Integer.MAX_VALUE;

    //System.out.println(mindist);
    for(int i=0;i<dict.length;i++){

    if(word1.equals(dict[i])){
    pos1=i;
    }
    if(word2.equals(dict[i])){
    pos2=i;
    }

    if(pos1!=-1 && pos2!=-1){
    mindist = Math.min(mindist, Math.abs(pos1-pos2));
    }

    }
    System.out.println(mindist);