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

LeetCode 126:单词接龙 II

LeetCode 126:单词接龙 II

在这里插入图片描述

问题本质与核心挑战

需找到 所有从 beginWordendWord 的最短转换序列,要求:

  • 相邻单词仅差一个字母;
  • 中间单词必须在 wordList 中。

核心挑战:

  • 如何高效找到最短路径(BFS 天然适合,但需记录路径);
  • 如何收集所有最短路径(需回溯前驱节点);
  • 如何避免重复搜索(通过层级控制和距离记录)。

核心思路:BFS 找层级 + 回溯找路径

1. 预处理:构建模式映射(邻接表优化)

将每个单词转换为 通配符模式(如 hot*oth*tho*),同一模式的单词互为相邻(差一个字母)。通过哈希表 patternMap 存储模式→单词列表,快速查找相邻单词。

2. BFS 遍历:记录距离和前驱
  • 距离 distance:记录每个单词到 beginWord 的最短步数(层级);
  • 前驱 predecessors:记录每个单词的前驱节点(用于回溯路径);
  • 层级控制:BFS 保证层级递增,一旦找到 endWord,后续层级更长,可提前终止。
3. 回溯生成路径

endWord 出发,递归回溯所有前驱节点,直到 beginWord,反转路径后收集结果。

算法步骤详解(以示例 1 为例:beginWord="hit", endWord="cog", wordList=["hot","dot","dog","lot","log","cog"]

步骤 1:预处理与边界检查
  • wordList 转成 Set(快速判断存在性);
  • endWord 不在 wordSet 中,直接返回空列表(如示例 2);
  • 构建 patternMap
    Map<String, List<String>> patternMap = new HashMap<>();
    for (String word : wordSet) {for (int i = 0; i < word.length(); i++) {String pattern = word.substring(0, i) + "*" + word.substring(i+1);patternMap.computeIfAbsent(pattern, k -> new ArrayList<>()).add(word);}
    }
    
    例如,hot 生成模式 *oth*tho*,对应单词 dotlothot 等。
步骤 2:BFS 遍历,记录距离和前驱
  • 初始化:队列加入 beginWorddistance 记录 beginWord 层级为 1
  • 遍历队列
    • 对当前单词 current,生成所有模式,找到相邻单词 neighbor
    • neighbor 未访问:记录距离(currentLevel+1)、前驱,加入队列;
    • neighbor 已访问且距离等于 currentLevel+1(同一层级的不同路径):添加前驱;
    • 若遇到 endWord,记录当前层级 shortestLevel,处理完当前层级后终止 BFS。

示例 1 的 BFS 过程(关键步骤)

层级当前单词相邻单词距离更新前驱记录
1hithothot→2hot: [hit]
2hotdot、lotdot→3, lot→3dot: [hot], lot: [hot]
3dotdogdog→4dog: [dot]
3lotloglog→4log: [lot]
4dogcogcog→5cog: [dog]
4logcogcog→5(补充前驱)cog: [dog, log]
步骤 3:回溯生成所有最短路径

endWord 出发,递归遍历前驱节点,直到 beginWord,反转路径后加入结果:

private void backtrack(String current, String beginWord, Map<String, List<String>> predecessors, List<String> path, List<List<String>> result) {if (current.equals(beginWord)) {List<String> reversed = new ArrayList<>(path);Collections.reverse(reversed);result.add(reversed);return;}for (String pre : predecessors.getOrDefault(current, new ArrayList<>())) {path.add(pre);backtrack(pre, beginWord, predecessors, path, result);path.remove(path.size() - 1);}
}

示例 1 的回溯过程

  • cog 的前驱是 doglog
    • dogdothothit → 路径 [hit, hot, dot, dog, cog]
    • loglothothit → 路径 [hit, hot, lot, log, cog]

完整代码(Java)

import java.util.*;class Solution {public List<List<String>> findLadders(String beginWord, String endWord, List<String> wordList) {List<List<String>> result = new ArrayList<>();Set<String> wordSet = new HashSet<>(wordList);// 边界:endWord不在字典中if (!wordSet.contains(endWord)) {return result;}// 构建模式映射:通配符模式→单词列表Map<String, List<String>> patternMap = new HashMap<>();for (String word : wordSet) {for (int i = 0; i < word.length(); i++) {String pattern = word.substring(0, i) + "*" + word.substring(i + 1);patternMap.computeIfAbsent(pattern, k -> new ArrayList<>()).add(word);}}// BFS初始化:队列、距离、前驱、最短层级Queue<String> queue = new LinkedList<>();queue.offer(beginWord);Map<String, Integer> distance = new HashMap<>();distance.put(beginWord, 1);Map<String, List<String>> predecessors = new HashMap<>();int shortestLevel = -1;while (!queue.isEmpty()) {if (shortestLevel != -1) break; // 已找到最短路径,终止后续层级int size = queue.size();for (int i = 0; i < size; i++) {String current = queue.poll();int currentLevel = distance.get(current);// 找到endWord,记录最短层级if (current.equals(endWord)) {shortestLevel = currentLevel;}// 生成所有相邻单词(通过模式匹配)for (int j = 0; j < current.length(); j++) {String pattern = current.substring(0, j) + "*" + current.substring(j + 1);List<String> neighbors = patternMap.getOrDefault(pattern, new ArrayList<>());for (String neighbor : neighbors) {if (!distance.containsKey(neighbor)) {// 未访问过,记录距离和前驱distance.put(neighbor, currentLevel + 1);predecessors.computeIfAbsent(neighbor, k -> new ArrayList<>()).add(current);queue.offer(neighbor);} else if (distance.get(neighbor) == currentLevel + 1) {// 同一层级的不同路径,补充前驱predecessors.computeIfAbsent(neighbor, k -> new ArrayList<>()).add(current);}}}}}// 未找到路径if (shortestLevel == -1) {return result;}// 回溯生成所有路径List<String> path = new ArrayList<>();path.add(endWord);backtrack(endWord, beginWord, predecessors, path, result);return result;}// 回溯函数:从endWord递归找前驱,直到beginWord,收集路径private void backtrack(String current, String beginWord, Map<String, List<String>> predecessors, List<String> path, List<List<String>> result) {if (current.equals(beginWord)) {List<String> reversed = new ArrayList<>(path);Collections.reverse(reversed);result.add(reversed);return;}// 遍历所有前驱,递归回溯for (String pre : predecessors.getOrDefault(current, new ArrayList<>())) {path.add(pre);backtrack(pre, beginWord, predecessors, path, result);path.remove(path.size() - 1); // 回溯}}
}

关键逻辑解析

  1. 模式映射:将单词转换为通配符模式,快速定位相邻单词,时间复杂度从 O(n²) 降为 O(n×L)L 为单词长度)。
  2. BFS 层级控制:保证首次到达 endWord 时的层级为最短路径,后续层级无需处理。
  3. 前驱记录:同一层级的不同路径需补充前驱,确保回溯时收集所有可能的最短路径。
  4. 回溯生成路径:从 endWord 反向遍历前驱,通过递归和路径回溯,生成所有符合条件的序列。

该方法结合 BFS 的层级优势回溯的路径收集能力,高效解决了“最短路径全收集”问题,时间复杂度为 O(N×L + P)N 为单词数,L 为单词长度,P 为最短路径数量),是处理此类问题的经典范式。

http://www.dtcms.com/a/312913.html

相关文章:

  • C语言的基本结构
  • http://localhost:8080/photos/xxx.png的本地图片访问方案
  • 电路原理图绘制专业实战教程2
  • 0803 思维导图+小项目
  • 【Redis学习路|第一篇】初步认识Redis
  • PPT写作五个境界--仅供学习交流使用
  • 构建企业级Web应用:AWS全栈架构深度解析
  • 力扣经典算法篇-39-有效的数独(二维数组和三维数组的应用)
  • AI 编程技巧、技术笔记
  • 安卓调javaScript Not find method “forceLogout“ implementatidsignature or namesp
  • 面向智能体的上下文工程:策略、实现与 LangGraph 实践
  • 基于单片机火灾报警系统/防火防盗系统设计
  • (9)NMPC非线性模型预测控制及机械臂ROS控制器实现
  • MCP-与本地大模型集成实现工具调用
  • 微服务的使用
  • java中Optional类的使用和注意采坑
  • DBMS设计 之2 从数据中台到三种中台
  • 常见的框架漏洞(Thinkphp,spring,Shiro)
  • 常见的框架漏洞
  • IO流-对象流
  • MCP革命:AI世界的“USB-C”接口如何重塑智能体与外部工具的连接
  • 均线:从市场脉搏到量子计算的时空密码
  • K8S几种常见CNI深入比较
  • Qt::AA_DontCreateNativeWidgetSiblings使用注意事项
  • 游戏设计原理
  • Flutter开发 dart异步
  • Linux网络编程 ---五种IO模型
  • 基于 Spring Boot + Vue 实现人脸采集功能全流程
  • Python----大模型(从预训练到分布式优化的核心技术解析)
  • 2、RabbitMQ的5种模式基本使用(Maven项目)