最短单词距离

141 阅读3分钟

Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情

1、题目描述

请设计一个类,使该类的构造函数能够接收一个字符串数组。然后再实现一个方法,该方法能够分别接收两个单词,并返回列表中这两个单词之间的最短距离。

实现 WordDistanc 类:

WordDistance(String[] wordsDict) 用字符串数组 wordsDict 初始化对象。
int shortest(String word1, String word2) 返回数组 worddict 中 word1 和 word2 之间的最短距离。

示例 1:

输入: 
["WordDistance", "shortest", "shortest"]
[[["practice", "makes", "perfect", "coding", "makes"]], ["coding", "practice"], ["makes", "coding"]]
输出:
[null, 3, 1

解释:

WordDistance wordDistance = new WordDistance(["practice", "makes", "perfect", "coding", "makes"]);
wordDistance.shortest("coding", "practice"); // 返回 3
wordDistance.shortest("makes", "coding");    // 返回 1

注意:

1 <= wordsDict.length <= 3 * 104
1 <= wordsDict[i].length <= 10
wordsDict[i] 由小写英文字母组成
word1 和 word2 在数组 wordsDict 中
word1 != word2
shortest 操作次数不大于 5000 

2、思路分析

我们需要使用哈希表来记录给出每一个单词的位置,查询的时候可以根据单词拿到其出现的位置,找到两个单词出现位置中距离最近的即可。

  • 使用哈希表记录单词出现位置
let wordMap = {};
for(let i = 0; i < wordsDict.length; i++){
    wordMap[wordsDict[i]] ? wordMap[wordsDict[i]].push(i) : wordMap[wordsDict[i]] = [i];
}
  • 找到两个单词最近距离
let d1 = this.wordMap[word1],d2 = this.wordMap[word2];
let res = Infinity;
for(let i = 0; i < d1.length; i++){
    for(let j = 0; j < d2.length; j++){
        res = Math.min(Math.abs(d1[i] - d2[j]),res);
    }
}

3、AC代码

/**
 * @param {string[]} wordsDict
 */
var WordDistance = function(wordsDict) {
    let wordMap = {};
    for(let i = 0; i < wordsDict.length; i++){
        wordMap[wordsDict[i]] ? wordMap[wordsDict[i]].push(i) : wordMap[wordsDict[i]] = [i];
    }
    this.wordMap = wordMap;
};

/** 
 * @param {string} word1 
 * @param {string} word2
 * @return {number}
 */
WordDistance.prototype.shortest = function(word1, word2) {
    let d1 = this.wordMap[word1],d2 = this.wordMap[word2];
    let res = Infinity;
    for(let i = 0; i < d1.length; i++){
        for(let j = 0; j < d2.length; j++){
            res = Math.min(Math.abs(d1[i] - d2[j]),res);
        }
    }
    return res;
};

/**
 * Your WordDistance object will be instantiated and called as such:
 * var obj = new WordDistance(wordsDict)
 * var param_1 = obj.shortest(word1,word2)
 */

4、题目延伸

题库中还有一道扩展题,题目如下:

(1)题目描述

给定一个字符串数组 wordsDict 和两个字符串 word1 和 word2 ,返回列表中这两个单词之间的最短距离。
注意:word1 和 word2 是有可能相同的,并且它们将分别表示为列表中 两个独立的单词 。

示例 1:

输入:wordsDict = ["practice", "makes", "perfect", "coding", "makes"], word1 = "makes", word2 = "coding"
输出:1

示例 2:

输入:wordsDict = ["practice", "makes", "perfect", "coding", "makes"], word1 = "makes", word2 = "makes"
输出:3

提示:

1 <= wordsDict.length <= 105
1 <= wordsDict[i].length <= 10
wordsDict[i] 由小写英文字母组成
word1 和 word2 都在 wordsDict 中

(2)思路分析

这一道题目与前面那道题目只有一个区别,就是在这道题目中word1 和 word2 是有可能相同的,并且它们将分别表示为列表中 两个独立的单词 ,也就是说两个相同单词的最短距离不是0,我们需要特殊处理一下。

if(word1 == word2){
    for(let i = 1; i < d1.length; i++){
        res = Math.min(d1[i] - d1[i - 1],res);
    }
    return res;
}

(3)AC代码

/**
 * @param {string[]} wordsDict
 * @param {string} word1
 * @param {string} word2
 * @return {number}
 */
var shortestWordDistance = function(wordsDict, word1, word2) {
    let wordMap = {};
    for(let i = 0; i < wordsDict.length; i++){
        wordMap[wordsDict[i]] ? wordMap[wordsDict[i]].push(i) : wordMap[wordsDict[i]] = [i];
    }
    let d1 = wordMap[word1],d2 = wordMap[word2];
    let res = Infinity;
    if(word1 == word2){
        for(let i = 1; i < d1.length; i++){
            res = Math.min(d1[i] - d1[i - 1],res);
        }
        return res;
    }
    for(let i = 0; i < d1.length; i++){
        for(let j = 0; j < d2.length; j++){
            res = Math.min(Math.abs(d1[i] - d2[j]),res);
        }
    }
    return res;
};