说在前面
🎈每天进行一道算法题目练习,今天的题目是“单词距离”。
问题描述
有个内含单词的超大文本文件,给定任意两个不同的单词,找出在这个文件中这两个单词的最短距离(相隔单词数)。如果寻找过程在这个文件中会重复多次,而每次寻找的单词不同,你能对此优化吗?
示例:
输入: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,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打打羽毛球🏸 ,平时也喜欢写些东西,既为自己记录📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解🙇,写错的地方望指出,定会认真改进😊,在此谢谢大家的支持,我们下文再见🙌。