LeetCode-面试题 17.11. 单词距离
题目如下:
有个内含单词的超大文本文件,给定任意两个不同的单词,找出在这个文件中这两个单词的最短距离(相隔单词数)。如果寻找过程在这个文件中会重复多次,而每次寻找的单词不同,你能对此优化吗?
示例:
输入:words = ["I","am","a","student","from","a","university","in","a","city"], word1 = "a", word2 = "student"
输出:1
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/find-closest-lcci
分析:
1.之前做这道题简单理解为只要找到两个单词所在下标返回下标之差最小的即可,于是有了下面这个答案
class Solution: def findClosest(self, words: List[str], word1: str, word2: str) -> int: return abs(words.index(word1) - words.index(word2))
但是有个问题,这种方法只能找一次,且只能找到最前面符合的单词下标,如果在一次查找中恰巧是最短距离则能够通过,而题目给的样例中就是这种情况。如果最短距离没有出现在最前面,而是在后面,那么此时查找则不符合。
进一步的
既然这种方式只能找一次,那么我能不能先找出所有word1和word2的下标存于两个数组中,然后循环判断最短距离?于是就有了下面这个代码
class Solution: def findClosest(self, words: List[str], word1: str, word2: str) -> int: ret = [] ret1 = [] ans = len(words) + 1 #先将ans赋值为最大,不可能有两个单词的距离比数组的长度加一还大 for i in range(len(words)): if words[i] == word1: ret.append(i) elif words[i] == word2: ret1.append(i) for i in range(len(ret)): for j in range(len(ret1)): if abs(ret[i] - ret1[j]) < ans: ans = min(ans, abs(ret[i] - ret1[j])) return ans
然后提交查看,可行。但是时间复杂度是O(n^2)。
2.再次做这个题目的时候看到最短两个字,第一反应是这几种方法:动态规划、贪心、回溯;但是感觉都不太合适
然后想的是用滑动窗口去做,右边界找到word1或word2中的一个单词时,左边界从当前位置到前一个指针的位置进行查找,当左边界也找到了两个单词中的一个且不等于前一个单词时,则记录下两个单词之前的距离并存入数组中,最后返回数组中最小的数即可。
提交查看通过。
3.双指针,参考的官方答案
(1)可以先初始化两个单词下标为-1,然后循环数组判断单词是否是两个单词中的一个,如果是,则更新该单词的下标。
(2)当两个指针都大于0,则说明找到了一组单词,更新其最短距离
(3)下一次循环继续更新两个单词的下标
class Solution: def findClosest(self, words: List[str], word1: str, word2: str) -> int: ans = len(words) index1, index2 = -1, -1 for i, word in enumerate(words): if word == word1: index1 = i elif word == word2: index2 = i if index1 >= 0 and index2 >= 0: ans = min(ans, abs(index1 - index2)) return ans
此方法时间复杂度为O(n)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构