面试题 17.11. 单词距离

195 阅读2分钟

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

说在前面

🎈每天进行一道算法题目练习,今天的题目是“单词距离”。

问题描述

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

示例:

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

提示:

words.length <= 100000

思路分析

首先我们应该要先理解一下题目的意思,题目要求的是要我们从单词列表words中计算单词word1单词word2的最短距离(也即是两单词中间相隔的单词数量)。
(1)暴力搜索法 这样一看题目不就很简单了嘛?直接两个for不就可以得出答案了吗?那么首先让我们来试试最简单直观的方法,首先进行第一次遍历,遍历遇到单词word1或者word2时,由当前位置向前遍历,直到遇到另一个单词,这时遍历过的距离就是在当前位置两个单词的最短距离,代码如下:

for(let i = 0; i < words.length; i++){
    if(words[i] == word1){
        let ind = i;
        while(ind-- && ind >= 0){
            if(words[ind] == word2) {
                res = Math.min(i - ind);
                break;
            }
        }
    if(words[i] == word2){
        let ind = i;
        while(ind-- && ind >= 0){
            if(words[ind] == word1) {
                res = Math.min(i - ind);
                break;
            }
        }
    }
}

这样的代码看起来是不是又长又没有效率,那么我们有什么办法可以对其进行优化呢?

(2)优化为一层循环 从上面代码中,我们可以看到每次遇到单词word1或者单词word2的时候,我们需要向前找到最近的另一个单词,那么如果我们事先将上一个位置出现的单词保存记录下来的话,是不是就可以免去这次的搜索查找了呢?我们可以再遍历过程中不断更新两个单词上一次出现的位置下标,需要计算的时候就可以直接取得,不用重复遍历计算,代码如下:

for(let i = 0; i < words.length; i++){
    if(words[i] == word1) ind1 = i;
    if(words[i] == word2) ind2 = i;
    res = Math.min(Math.abs(ind1 - ind2),res);
}

这样的代码看起来是不是就比上面的那代码简洁多了呢?完整代码如下:

AC代码

/**
 * @param {string[]} words
 * @param {string} word1
 * @param {string} word2
 * @return {number}
 */
 var findClosest = function(words, word1, word2) {
     let res = Infinity,ind1 = -Infinity,ind2 = Infinity;
     for(let i = 0; i < words.length; i++){
         if(words[i] == word1) ind1 = i;
         if(words[i] == word2) ind2 = i;
         res = Math.min(Math.abs(ind1 - ind2),res);
     }
     return res;
};

说在后面

🎉这里是JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打打羽毛球🏸 ,平时也喜欢写些东西,既为自己记录📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解🙇,写错的地方望指出,定会认真改进😊,在此谢谢大家的支持,我们下文再见🙌。