[Leetcode] Shortest Word Distance 最短单词间距
Shortest Word Distance
Given a list of words and two words word1 and word2, 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.
双指针法
复杂度
时间 O(N) 空间 O(1)
思路
一个指针指向word1上次出现的位置,一个指针指向word2上次出现的位置。因为两个单词如果比较接近的话,肯定是相邻的word1和word2的位置之差,所以我们只要每次得到一个新位置和另一个单词的位置比较一下就行了。
代码
public class Solution { public int shortestDistance(String[] words, String word1, String word2) { int idx1 = -1, idx2 = -1, distance = Integer.MAX_VALUE; for(int i = 0; i < words.length; i++){if(words[i].equals(word1)){ idx1 = i; // 第一次写入idx就先不比较 if(idx2 != -1) distance = Math.min(distance, idx1 - idx2);}if(words[i].equals(word2)){ idx2 = i; // 第一次写入idx就先不比较 if(idx1 != -1) distance = Math.min(distance, idx2 - idx1);} } return distance; }}
Shortest Word Distance 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.
哈希表法
复杂度
时间 O(N) 空间 O(N)
思路
因为会多次调用,我们不能每次调用的时候再把这两个单词的下标找出来。我们可以用一个哈希表,在传入字符串数组时,就把每个单词的下标找出存入表中。这样当调用最短距离的方法时,我们只要遍历两个单词的下标列表就行了。具体的比较方法,则类似merge two list,每次比较两个list最小的两个值,得到一个差值。然后把较小的那个给去掉。因为我们遍历输入数组时是从前往后的,所以下标列表也是有序的。
代码
public class WordDistance { HashMap<String, List<Integer>> map = new HashMap<String, List<Integer>>(); public WordDistance(String[] words) { // 统计每个单词出现的下标存入哈希表中 for(int i = 0; i < words.length; i++){List<Integer> cnt = map.get(words[i]);if(cnt == null){ cnt = new ArrayList<Integer>();}cnt.add(i);map.put(words[i], cnt); } } public int shortest(String word1, String word2) { List<Integer> idx1 = map.get(word1); List<Integer> idx2 = map.get(word2); int distance = Integer.MAX_VALUE; int i = 0, j = 0; // 每次比较两个下标列表最小的下标,然后把跳过较小的那个 while(i < idx1.size() && j < idx2.size()){distance = Math.min(Math.abs(idx1.get(i) - idx2.get(j)), distance);if(idx1.get(i) < idx2.get(j)){ i++;} else { j++;} } return distance; }}
Shortest Word Distance III
This is a follow up of Shortest Word Distance. The only difference is now word1 could be the same as word2.
Given a list of words and two words word1 and word2, return the shortest distance between these two words in the list.
word1 and word2 may be the same and they represent two individual words in the list.
For example, Assume that words =
["practice", "makes", "perfect", "coding", "makes"]
.Given word1 = “makes”, word2 = “coding”, return 1. Given word1 = "makes", word2 = "makes", return 3.
Note: You may assume word1 and word2 are both in the list.
双指针法
复杂度
时间 O(N) 空间 O(N)
思路
这题和I是一样的,唯一不同的是对于word1和word2相同的时候,我们要区分第一次遇到和第二次遇到这个词。这里加入了一个turns,如果是相同单词的话,每次遇到一个单词turn加1,这样可以根据turn来判断是否要switch。
代码
public class Solution { public int shortestWordDistance(String[] words, String word1, String word2) { int idx1 = -1, idx2 = -1, distance = Integer.MAX_VALUE, turn = 0, inc = (word1.equals(word2) ? 1 : 0); for(int i = 0; i < words.length; i++){if(words[i].equals(word1) && turn % 2 == 0){ idx1 = i; if(idx2 != -1) distance = Math.min(distance, idx1 - idx2); turn += inc;} else if(words[i].equals(word2)){ idx2 = i; if(idx1 != -1) distance = Math.min(distance, idx2 - idx1); turn += inc;} } return distance; }}