当前位置: 首页 > news >正文

LeetCode第245题_最短单词距离III

LeetCode第245题:最短单词距离III

问题描述

给定一个字符串数组 wordsDict 和两个字符串 word1word2,返回列表中这两个单词之间的最短距离。

注意,word1word2 可能是同一个单词,且它们在列表中可能会出现多次。word1word2 是区分大小写的。

难度:中等

示例

示例 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 <= 3 * 10^4
  • 1 <= wordsDict[i].length, word1.length, word2.length <= 10
  • wordsDict[i], word1, 和 word2 只包含小写英文字母
  • word1word2wordsDict 中都出现至少一次

解题思路

这个问题是 LeetCode 243 “最短单词距离” 的进一步扩展版本。主要区别在于,本题允许 word1word2 是相同的单词。当两个单词相同时,我们需要找到同一个单词的两个不同出现位置之间的最短距离。

方法一:双指针法

我们可以修改之前的一次遍历方法,特别处理 word1word2 相同的情况:

  1. 如果 word1word2 不同,使用与 LeetCode 243 相同的方法:

    • 遍历数组,记录两个单词最后出现的位置
    • 当找到一个单词时,计算与另一个单词最后位置的距离
  2. 如果 word1word2 相同,我们需要找到同一个单词的两个连续出现位置之间的最短距离:

    • 记录单词最后两次出现的位置
    • 计算这两个位置之间的距离

方法二:使用位置数组

另一种方法是分别收集 word1word2 出现的所有位置,然后计算它们之间的最短距离:

  1. 遍历数组,分别记录 word1word2 的所有出现位置
  2. 如果 word1word2 不同,比较两个位置数组中每对位置之间的距离
  3. 如果 word1word2 相同,比较位置数组中相邻位置之间的距离

代码实现

方法一:双指针法

C#实现
public class Solution {public int ShortestWordDistance(string[] wordsDict, string word1, string word2) {int minDistance = int.MaxValue;int index1 = -1, index2 = -1;bool isSameWord = word1.Equals(word2);for (int i = 0; i < wordsDict.Length; i++) {if (wordsDict[i].Equals(word1)) {if (isSameWord) {// 如果是相同的单词,当前位置与上一个位置比较if (index1 != -1) {minDistance = Math.Min(minDistance, i - index1);}index1 = i;} else {index1 = i;// 如果已经找到word2,计算距离if (index2 != -1) {minDistance = Math.Min(minDistance, Math.Abs(index1 - index2));}}} else if (!isSameWord && wordsDict[i].Equals(word2)) {index2 = i;// 如果已经找到word1,计算距离if (index1 != -1) {minDistance = Math.Min(minDistance, Math.Abs(index1 - index2));}}}return minDistance;}
}
Python实现
class Solution:def shortestWordDistance(self, wordsDict: List[str], word1: str, word2: str) -> int:min_distance = float('inf')index1 = index2 = -1is_same_word = word1 == word2for i, word in enumerate(wordsDict):if word == word1:if is_same_word:# 如果是相同的单词,当前位置与上一个位置比较if index1 != -1:min_distance = min(min_distance, i - index1)index1 = ielse:index1 = i# 如果已经找到word2,计算距离if index2 != -1:min_distance = min(min_distance, abs(index1 - index2))elif not is_same_word and word == word2:index2 = i# 如果已经找到word1,计算距离if index1 != -1:min_distance = min(min_distance, abs(index1 - index2))return min_distance
C++实现
class Solution {
public:int shortestWordDistance(vector<string>& wordsDict, string word1, string word2) {int minDistance = INT_MAX;int index1 = -1, index2 = -1;bool isSameWord = (word1 == word2);for (int i = 0; i < wordsDict.size(); i++) {if (wordsDict[i] == word1) {if (isSameWord) {// 如果是相同的单词,当前位置与上一个位置比较if (index1 != -1) {minDistance = min(minDistance, i - index1);}index1 = i;} else {index1 = i;// 如果已经找到word2,计算距离if (index2 != -1) {minDistance = min(minDistance, abs(index1 - index2));}}} else if (!isSameWord && wordsDict[i] == word2) {index2 = i;// 如果已经找到word1,计算距离if (index1 != -1) {minDistance = min(minDistance, abs(index1 - index2));}}}return minDistance;}
};

方法二:使用位置数组

C#实现
public class Solution {public int ShortestWordDistance(string[] wordsDict, string word1, string word2) {List<int> positions1 = new List<int>();List<int> positions2 = new List<int>();// 收集位置for (int i = 0; i < wordsDict.Length; i++) {if (wordsDict[i].Equals(word1)) {positions1.Add(i);}if (wordsDict[i].Equals(word2)) {positions2.Add(i);}}// 如果单词相同,positions1和positions2包含相同的位置if (word1.Equals(word2)) {int minDist = int.MaxValue;// 计算相邻位置之间的最小距离for (int i = 1; i < positions1.Count; i++) {minDist = Math.Min(minDist, positions1[i] - positions1[i - 1]);}return minDist;} else {// 计算两个位置数组之间的最小距离int minDist = int.MaxValue;int i = 0, j = 0;while (i < positions1.Count && j < positions2.Count) {minDist = Math.Min(minDist, Math.Abs(positions1[i] - positions2[j]));// 移动指向较小位置的指针if (positions1[i] < positions2[j]) {i++;} else {j++;}}return minDist;}}
}
Python实现
class Solution:def shortestWordDistance(self, wordsDict: List[str], word1: str, word2: str) -> int:positions1 = [i for i, word in enumerate(wordsDict) if word == word1]positions2 = [i for i, word in enumerate(wordsDict) if word == word2]# 如果单词相同,计算相邻位置之间的最小距离if word1 == word2:return min(positions1[i] - positions1[i-1] for i in range(1, len(positions1)))# 使用双指针计算两个位置数组之间的最小距离i = j = 0min_distance = float('inf')while i < len(positions1) and j < len(positions2):min_distance = min(min_distance, abs(positions1[i] - positions2[j]))if positions1[i] < positions2[j]:i += 1else:j += 1return min_distance
C++实现
class Solution {
public:int shortestWordDistance(vector<string>& wordsDict, string word1, string word2) {vector<int> positions1;vector<int> positions2;// 收集位置for (int i = 0; i < wordsDict.size(); i++) {if (wordsDict[i] == word1) {positions1.push_back(i);}if (wordsDict[i] == word2) {positions2.push_back(i);}}// 如果单词相同,positions1和positions2包含相同的位置if (word1 == word2) {int minDist = INT_MAX;// 计算相邻位置之间的最小距离for (int i = 1; i < positions1.size(); i++) {minDist = min(minDist, positions1[i] - positions1[i - 1]);}return minDist;} else {// 计算两个位置数组之间的最小距离int minDist = INT_MAX;int i = 0, j = 0;while (i < positions1.size() && j < positions2.size()) {minDist = min(minDist, abs(positions1[i] - positions2[j]));// 移动指向较小位置的指针if (positions1[i] < positions2[j]) {i++;} else {j++;}}return minDist;}}
};

性能分析

方法一:双指针法

  • 时间复杂度:O(n),其中 n 是 wordsDict 的长度。我们只需遍历数组一次。
  • 空间复杂度:O(1),只需要几个变量来存储位置和最短距离。

方法二:使用位置数组

  • 时间复杂度:O(n),其中 n 是 wordsDict 的长度。虽然我们需要遍历数组来收集位置,但后续的双指针比较只需 O(m+k) 时间,其中 m 和 k 是两个单词出现的次数。总体复杂度仍为 O(n)。
  • 空间复杂度:O(m+k),其中 m 和 k 是两个单词出现的次数。我们需要存储每个单词的所有位置。

方法对比

方法时间复杂度空间复杂度优势劣势
双指针法O(n)O(1)空间占用少实现稍复杂
位置数组O(n)O(m+k)实现清晰空间占用较大

方法优化

对于方法一,我们可以进一步优化代码结构,使其更简洁、更易理解:

def shortestWordDistance(wordsDict, word1, word2):min_distance = float('inf')last_pos = -1for i, word in enumerate(wordsDict):if word == word1 or word == word2:# 如果找到目标单词if last_pos != -1 and (word1 == word2 or word != wordsDict[last_pos]):# 如果是相同单词,或者与上一个找到的单词不同min_distance = min(min_distance, i - last_pos)last_pos = ireturn min_distance

这个优化版本统一处理了相同和不同单词的情况,代码更加简洁明了。

常见错误与陷阱

  1. 忽略相同单词的特殊处理:当 word1word2 相同时,需要特别处理。不能简单地比较每对位置,而应该比较相邻位置。
  2. 在位置数组方法中没有正确处理相同单词:当单词相同时,positions1 和 positions2 包含相同的位置,不能直接使用双指针比较。
  3. 数组越界:在计算相邻位置距离时,需要确保数组中至少有两个元素。

相关题目

  • LeetCode 第243题:最短单词距离
  • LeetCode 第244题:最短单词距离 II
  • LeetCode 第246题:中心对称数
http://www.xdnf.cn/news/783523.html

相关文章:

  • PDF.js无法显示数字签名
  • ARM GIC V3概述
  • 预览pdf(url格式和blob格式)
  • 【C/C++】初步了解享元模式
  • Linux账号和权限管理
  • ubuntu 20.04挂载固态硬盘
  • 什么是“音节”?——语言构成的节拍单位
  • 【Java Web】7.事务管理AOP
  • 【Spring】Spring哪些源码解决了哪些问题P1
  • WINUI——Magewell视频捕捉开发手记
  • “packageManager“: “pnpm@9.6.0“ 配置如何正确启动项目?
  • Vue-ref 与 props
  • 不止抓请求:5种开发场景中的抓包组合策略(含 Charles 等工具)
  • SpringBoot 数据库导入导出 Xlsx文件的导入与导出 全量导出 数据库导出表格 数据处理 外部数据
  • DHCP 动态主机配置协议(Dynamic host configuration protocol)逐层封装过程: DHCP --> UDP --> IP
  • 从0到1,带你走进Flink的世界
  • iOS 电子书听书功能的实现
  • [yolov11改进系列]基于yolov11使用FasterNet替换backbone用于轻量化网络的python源码+训练源码
  • React---day8
  • Express 集成Sequelize+Sqlite3 默认开启WAL 进程间通信 Conf 打包成可执行 exe 文件
  • mobilnet v4 部署笔记
  • [yolov11改进系列]基于yolov11引入自集成注意力机制SEAM解决遮挡问题的python源码+训练源码
  • 机器学习实战36-基于遗传算法的水泵调度优化项目研究与代码实现
  • 华为云Flexus+DeepSeek征文|基于华为云Flexus X实例的小说转语音助手应用构建实录
  • java int 颜色值转换为string 不带透明度
  • Numpy入门2——视图和副本、伪随机数、切片和索引、数组的轴操作
  • 从0到1认识EFK
  • Oracle 用户/权限/角色管理
  • Linux随记(十八)
  • ElasticSearch+Gin+Gorm简单示例