class Solution { public int ladderLength(String beginWord, String endWord, List<String> wordList) { HashSet<String> wordSet = new HashSet<>(wordList); //替换掉题目中List结构,加速查找 if (!wordSet.contains(endWord)) return 0; //如果目标顶点不在图中,直接返回0 HashMap<String, Integer> map = new HashMap<>(); //用来存储已访问的节点,并存储其在路径上的位置,相当于BFS算法中的isVisted功能 Queue<String> q = new LinkedList<>(); //构建队列,实现广度优先遍历 q.add(beginWord); //加入源顶点 map.put(beginWord, 1); //添加源顶点为“已访问”,并记录它在路径的位置 while (!q.isEmpty()) { //开始遍历队列中的顶点 String word = q.poll(); //记录现在正在处理的顶点 int level = map.get(word); //记录现在路径的长度 for (int i = 0; i < word.length(); i++) { char[] wordLetter = word.toCharArray(); for (char j = 'a'; j <= 'z'; j++) { if (wordLetter[i] == j) continue; wordLetter[i] = j; //对于每一位字母,分别替换成另外25个字母 String check = new String(wordLetter); if (check.equals(endWord)) return map.get(word) + 1; //如果已经抵达目标节点,返回当前路径长度+1 if (wordSet.contains(check) && !map.containsKey(check)) { //如果字典中存在邻接节点,且这个邻接节点还未被访问 map.put(check, level + 1); //标记这个邻接节点为已访问,记录其在路径上的位置 q.add(check); //加入队列,以供广度搜索 } } } } return 0; } }
数据结构:
HashSet<String> wordSet 实用hash存储第三个参数单词字典,加速查找
HashMap<String, Integer> map 存储已经访问过的节点,相当于visited
LinkedList<Object> q 主循环判断的Stack
算法流程:
q中添加源单词,同时在map中添加此单词,表示已占用
循环q
取出q中的栈顶的值(poll) -> word (map中仍然占用)
查询栈的深度 -> level
循环word中每一个字符
找到一个合理的匹配 ->check
判断check是否是目标单词
是:返回 level + 1
不是:将check加入q,并在map中锁定check
循环完毕,所有在单词列表中的词都被锁定,无法添加进入q,则返回0,表示未找到
补充一个python的实现:
1 class Solution: 2 def ladderLength(self, beginWord: str, endWord: str, wordList: 'List[str]') -> int: 3 wordset = set(wordList) 4 if endWord not in wordset: 5 return 0 6 alpher = ['a','b','c','d','e','f','g', 7 'h','i','j','k','l','m','n', 8 'o','p','q','r','s','t', 9 'u','v','w','x','y','z'] 10 wordmap = {} 11 q = [] 12 q.append(beginWord) 13 wordmap[beginWord] = 1 14 while len(q) > 0: 15 n = len(q) 16 temp = [] 17 while n > 0: 18 n -= 1 19 word = q.pop() 20 level = wordmap[word] 21 for i in range(len(word)): 22 for j in range(len(alpher)): 23 if word[i] == alpher[j]: 24 continue 25 check = word[:i] + alpher[j] + word[i+1:] 26 if check == endWord: 27 return level + 1 28 #minLength = min(minLength,level + 1) 29 if check in wordset and check not in wordmap: 30 wordmap[check] = level + 1 31 temp.append(check) 32 if len(temp) > 0: 33 q = temp[:] 34 return 0
注意加粗部分的代码,与java的语法是有区别,主要是判断q是否为空。