244 SWD II

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.

Note: You may assume that word1 does not equal to word2, and word1 and word2 are both in the list.


分析

实现一个class,能够利用数组words构造对象:

WordDistance wd = new WordDistance(words);

并实现可以运用上对象的方法,以求最短距离:

int shortestDis = wd.shortest(word1, word2);

与243的区别: 该题含有OOP的思想

思路1

设计class得考虑的问题:

  • private variable(fields)
  • constructor
  • methods

1.private variable

private String[] words;

2.constructor

this.words = words;

3.method: shortest(String word1, String word2)

求最短距离的方法具体实现类似于243

思路1具体实现遇到的问题

1.ArrayList 的排序方法

Collections.sort(AL);

2.代码结果正确但Time limit exceeded

public class WordDistance {

    /*///////////ArrayList////////////
    //fields
    private String[] words;

    //constructor
    public WordDistance(String[] words) {
        this.words = words; 
    }


    //method
    public int shortest(String word1, String word2) {

        int dis = 0;

        //find word1 & word2 's index
        ArrayList<Integer> word1Pos = new ArrayList<Integer>();
        word1Pos = findPos(word1);
        ArrayList<Integer> word2Pos = new ArrayList<Integer>();
        word2Pos = findPos(word2);

        //find shortest distance
        //1.find all possible distance
        ArrayList<Integer> disAL = new ArrayList<Integer>();
        for(int i=0; i < word1Pos.size(); i++) {
            for(int j=0; j < word2Pos.size(); j++) {
                disAL.add(Math.abs(word1Pos.get(i) - word2Pos.get(j)));
            }
        }
        //2.find shortest
        Collections.sort(disAL);
        dis = disAL.get(0);

        return dis;

    }

    private ArrayList<Integer> findPos(String word) {
        ArrayList<Integer> wordPos = new ArrayList<Integer>();
        for(int i=0; i < words.length; i++) {
            if(word.equals(words[i])) {
                wordPos.add(i);
            }
        }
        return wordPos;
    }
}

思路2:将ArrayList换成Array

思路2具体实现遇到的问题:

1.各数组的初始化长度

int[] wordPos = new int[words.length-1];
int[] disA = new int[(words.length-1)*(words.lenght-1)];

2.java平方函数

import java.util.*;
Math.pow(i, 2);

3.数组初始化是0,因此求完wordPos后无法确定数组中0的含义是否是真实的index信息

结论:思路破产

思路3:利用Hashmap

分析: 之前的思路由于每一次运用method都会重新查找wordPos信息,所以当调用许多次method就会导致很耗时,因此如果在创建对象的时候直接生成wordPos的Hashmap,之后的信息这可以直接使用。

1.comstructor

1)创建对象的时候就构建一个hashmap,key是string,value是对应string在数组words中的index。

2)由于每个word对应的index不止一个,因此hashmap的value为ArrayList

2.private variables

private HashMap<String, ArrayList<Integer>> wordPos = new HashMap<String, ArrayList<Integer>>();

3.method

类似思路1

思路3实现中遇到的问题

1.HashMap 的一些操作

containsKey(Object key)
put(K key, V value)
get(Object key)

2.constructor中如何构建HashMap

利用containsKey来看Map中有没有对应的key,如果有,用get取出对应ArrayList的地址,再利用add加入index;如果没有,先用put来给key连上一个ArrayList的对象,用get取出对应ArrayList的地址,再利用add加入index。

Accepted Code

//jiayuanh_0128: 25ms, Your runtime beats 14.50% of java submissions.
////////HashMap/////////
//fields
private HashMap<String, ArrayList<Integer>> wordPosHM = new HashMap<String, ArrayList<Integer>>();

//constructor
public WordDistance(String[] words) {
    for(int i=0; i< words.length; i++) {
        if(wordPosHM.containsKey(words[i])) {
            wordPosHM.get(words[i]).add(i);
        }
        else {
            wordPosHM.put(words[i], new ArrayList<Integer>());
            wordPosHM.get(words[i]).add(i);
        }
    }
}

//method
public int shortest(String word1, String word2) {
    int dis=0;

    //find word1 & word2 's index
    ArrayList<Integer> word1Pos = wordPosHM.get(word1);
    ArrayList<Integer> word2Pos = wordPosHM.get(word2);

    //find shortest distance
    //1.find all possible distance
    ArrayList<Integer> disAL = new ArrayList<Integer>();
    for(int i=0; i < word1Pos.size(); i++) {
        for(int j=0; j < word2Pos.size(); j++) {
            disAL.add(Math.abs(word1Pos.get(i) - word2Pos.get(j)));
        }
    }
    //2.find shortest
    Collections.sort(disAL);
    dis = disAL.get(0);

    return dis;
}

results matching ""

    No results matching ""