题目
leetCode链接:https://leetcode.cn/problems/find-closest-lcci/
面试题17.11. 单词距离
有个内含单词的超大文本文件,给定任意两个不同的单词,找出在这个文件中这两个单词的最短距离(相隔单词数)。如果寻找过程在这个文件中会重复多次,而每次寻找的单词不同,你能对此优化吗?
示例:
输入:words = ["I","am","a","student","from","a","university","in","a","city"], word1 = "a", word2 = "student"
输出:1
思路
第一个想到的思路是暴力求解,对每个words中的word1,寻找它和每个word2之间的距离,去最小值,重复直到没有word1为止。复杂度过高(
n
2
n^2
n2),直接pass。
第二个思路就是使用更简单的指针下标记录word1和word2的为止,从头开始遍历,如果发现单词为word1或者word2就记录下标,并计算两个下标距离和之前记录的距离取最小值即可。
对于进阶题,多个key对同一列表做查找很容易想到hash map存储每个单词对应的下标,这样就可以直接做查找了。首先将words放入hash map,然后对于查找的每一对单词,用两个指针(index1,index2)标记两个单词对应的下标list开头,然后按如下规则向后移动查找即可:
- 如果 index1 < index2,则将index1 移动到下一个word1 的下标;
- 如果 index1 > index2,则将index2 移动到下一个word2 的下标。
解题
python实现
class Solution:
def findClosest(self, words: List[str], word1: str, word2: str) -> int:
result = len(words)
i1 = -1
i2 = -1
for k,v in enumerate(words):
if v==word1:
i1=k
if v==word2:
i2=k
if i1>=0 and i2>=0:
result=min(result,abs(i1-i2))
return result
golang实现
func findClosest(words []string, word1 string, word2 string) int {
result := len(words)
i1, i2 := -1, -1
for k, v := range words {
if v == word1 {
i1 = k
} else if v == word2 {
i2 = k
}
if i1 >= 0 && i2 >= 0 {
result = min(result, abs(i1-i2))
}
}
return result
}
func min(a, b int) int {
if a > b {
return b
}
return a
}
func abs(a int) int {
if a >= 0 {
return a
}
return -a
}
进阶
python实现
class Solution:
def findMoreClosest(self, words: List[str], word_pairs: List[List[str]]) -> List[int]:
hash_map = dict()
for k, v in enumerate(words):
if v not in hash_map.keys():
hash_map[v] = [k]
else:
hash_map[v].append(k)
result = []
for pairs in word_pairs:
word1 = pairs[0]
word2 = pairs[1]
word1_index_list = hash_map.get(word1, [])
word2_index_list = hash_map.get(word2, [])
ans = len(words)
i, j = 0, 0
while i < len(word1_index_list) and j < len(word2_index_list):
i1 = word1_index_list[i]
i2 = word2_index_list[j]
ans = min(ans, abs(i1 - i2))
if i1 < i2:
i += 1
else:
j += 1
result.append(ans)
return result
golang实现
懒得写了基本就是转译一下上面的python吧
复杂度
时间复杂度: O ( n ) O(n) O(n),只需要遍历一次列表。进阶算法对于输入的每一对word1和word2,复杂度为 O ( n ) O(n) O(n),其中放入hash map复杂度为 O ( n ) O(n) O(n),双指针遍历复杂度为 O ( n ) O(n) O(n)。
空间复杂度: O ( 1 ) O(1) O(1)。进阶算法复杂度为 O ( n ) O(n) O(n),即为hash map占据空间大小。
总结
昨日遇到困难睡大觉了,今日没啥好说的,较为简单思路也很清晰的题目。
进阶版本双指针遍历思路需要多看一下,比我之前自己写的优雅太多了。