单词接龙
问题陈述
给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列的长度。转换需遵循如下规则:
每次转换只能改变一个字母。
转换过程中的中间单词必须是字典中的单词。
说明:
如果不存在这样的转换序列,返回 0。
所有单词具有相同的长度。
所有单词只由小写字母组成。
字典中不存在重复的单词。
你可以假设 beginWord 和 endWord 是非空的,且二者不相同。
1 2 3 4 5 6 7 8 9 10 11
| 输入: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"]
输出: 5
解释: 一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog", 返回它的长度 5。
|
思路分析
根据题意分析:已知开头和结尾词,从词集中找到类似词(具有两个相同字母)进行接龙。
1、如果词集中没有尾词,则直接返回0。
2、层序遍历。将首词加入队列,判断词集中是否有可以与之接龙的词。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| class Solution { public int ladderLength(String beginWord, String endWord, List<String> wordList) { if(!wordList.contains(endWord)){ return 0; } boolean[] visited=new boolean[wordList.size()]; int idx=wordList.indexOf(beginWord); if(idx!=-1){ visited[idx]=true; } Queue<String> queue=new LinkedList<>(); queue.offer(beginWord); int count=0; while(!queue.isEmpty()){ count++; int size=queue.size(); while(size-->0){ String s1=queue.poll(); for(int i=0;i<wordList.size();i++){ String s2=wordList.get(i); if(visited[i]){ continue; } if(!canConvert(s1,s2)){ continue; } if(s2.equals(endWord)){ return count+1; } visited[i]=true; queue.offer(s2); } } } return 0; } public boolean canConvert(String s1,String s2){ int count=0; for(int i=0;i<s2.length();i++){ if(s1.charAt(i)!=s2.charAt(i)){ count++; } if(count>1){ return false; } } return count==1; } }
|
优化:上述方法符合一般流程但效率过低,考虑使用首尾BFS并优化比较过程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| class Solution { public int ladderLength(String beginWord, String endWord, List<String> wordList) { int end = wordList.indexOf(endWord); if (end == -1) { return 0; } wordList.add(beginWord); Queue<String> queue1 = new LinkedList<>(); Queue<String> queue2 = new LinkedList<>(); Set<String> visited1 = new HashSet<>(); Set<String> visited2 = new HashSet<>(); queue1.offer(beginWord); queue2.offer(endWord); visited1.add(beginWord); visited2.add(endWord); int count = 0; Set<String> allWordSet = new HashSet<>(wordList);
while (!queue1.isEmpty() && !queue2.isEmpty()) { count++; if (queue1.size() > queue2.size()) { Queue<String> tmp = queue1; queue1 = queue2; queue2 = tmp; Set<String> t = visited1; visited1 = visited2; visited2 = t; } int size1 = queue1.size(); while (size1-- > 0) { String s = queue1.poll(); char[] chars = s.toCharArray(); for (int j = 0; j < s.length(); ++j) { char c0 = chars[j]; for (char c = 'a'; c <= 'z'; ++c) { chars[j] = c; String newString = new String(chars); if (visited1.contains(newString)) { continue; } if (visited2.contains(newString)) { return count + 1; } if (allWordSet.contains(newString)) { queue1.offer(newString); visited1.add(newString); } } chars[j] = c0; } } } return 0; } }
|