力扣每日一题-0527面试题 17.11. 单词距离

78 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情

有个内含单词的超大文本文件,给定任意两个不同的单词,找出在这个文件中这两个单词的最短距离(相隔单词数)。如果寻找过程在这个文件中会重复多次,而每次寻找的单词不同,你能对此优化吗?

示例:

输入:words = ["I","am","a","student","from","a","university","in","a","city"], word1 = "a", word2 = "student"
输出:1

提示:

  • words.length <= 100000

一次遍历

最直观的做法是遍历数组 words\textit{words},对于数组中的每个 word1\textit{word}_1,遍历数组 words\textit{words} 找到每个 word2\textit{word}_2 并计算距离。该做法在最坏情况下的时间复杂度是 O(n2)O(n^2),需要优化。

为了降低时间复杂度,需要考虑其他的做法。从左到右遍历数组 words\textit{words},当遍历到 word1\textit{word}_1 时,如果已经遍历的单词中存在 word2\textit{word}_2,为了计算最短距离,应该取最后一个已经遍历到的 word2\textit{word}_2 所在的下标,计算和当前下标的距离。同理,当遍历到 word2\textit{word}_2 时,应该取最后一个已经遍历到的 word1\textit{word}_1 所在的下标,计算和当前下标的距离。

基于上述分析,可以遍历数组一次得到最短距离,将时间复杂度降低到 O(n)O(n)

index1\textit{index}_1index2\textit{index}_2 分别表示数组 words\textit{words} 已经遍历的单词中的最后一个 word1\textit{word}_1 的下标和最后一个 word2\textit{word}_2 的下标,初始时 index1=index2=1\textit{index}_1 = \textit{index}_2 = -1。遍历数组 words\textit{words},当遇到 word1\textit{word}_1word2\textit{word}_2 时,执行如下操作:

  1. 如果遇到 word1\textit{word}_1,则将 index1\textit{index}_1 更新为当前下标;如果遇到 word2\textit{word}_2,则将 index2\textit{index}_2 更新为当前下标。
  2. 如果 index1\textit{index}_1index2\textit{index}_2 都非负,则计算两个下标的距离 index1index2|\textit{index}_1 - \textit{index}_2|,并用该距离更新最短距离。

遍历结束之后即可得到 word1\textit{word}_1word2\textit{word}_2 的最短距离。

var findClosest = function(words, word1, word2) {
    const length = words.length;
    let ans = length;
    let index1 = -1, index2 = -1;
    for (let i = 0; i < length; i++) {
        const word = words[i];
        if (word === word1) {
            index1 = i;
        } else if (word === word2) {
            index2 = i;
        }
        if (index1 >= 0 && index2 >= 0) {
            ans = Math.min(ans, Math.abs(index1 - index2));
        }
    }
    return ans;
};