Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence from beginWord to endWord, such that:c++
Only one letter can be changed at a timespa
Each intermediate word must exist in the word listcode
For example,orm
Given:
beginWord ="hit"
endWord ="cog"
wordList =["hot","dot","dog","lot","log"]
As one shortest transformation is"hit" -> "hot" -> "dot" -> "dog" -> "cog"
,
return its length5
.remNote:字符串
Return 0 if there is no such transformation sequence.get
All words have the same length.it
All words contain only lowercase alphabetic characters.io
典型的BFS题。一层一层的找,分别对应修改一个字符,两个字符,三个字符...直至发现结尾字符串, 注意用一个Set寸已经访问过的字符串,避免重复。form
time: O(n), space: O(n)
public class Solution { public int ladderLength(String beginWord, String endWord, Set<String> wordList) { Queue<String> q = new LinkedList<String>(); q.add(beginWord); Set<String> visited = new HashSet<String>(); visited.add(beginWord); int level = 0; while (!q.isEmpty()) { int len = q.size(); level++; for (int i = 0; i < len; i++) { String word = q.remove(); for (int j = 0; j < word.length(); j++) { char[] chars = word.toCharArray(); for (char c = 'a'; c <= 'z'; c++) { chars[j] = c; String nextWord = new String(chars); if (nextWord.equals(endWord)) { return level + 1; } if (!visited.contains(nextWord) && wordList.contains(nextWord)) { q.add(nextWord); visited.add(nextWord); } } } } } return 0; } }
Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformation sequence(s) from beginWord to endWord, such that:
Only one letter can be changed at a time
Each intermediate word must exist in the word list
For example,
Given:
beginWord ="hit"
endWord ="cog"
wordList =["hot","dot","dog","lot","log"]
Return[ ["hit","hot","dot","dog","cog"], ["hit","hot","lot","log","cog"] ]Note:
All words have the same length.
All words contain only lowercase alphabetic characters.
若是要返回全部的结果,问题变复杂了些。由于用BFS相对于DFS的劣势就是不方便存储结果。这种须要返回全部结果的,仍是应该从DFS考虑,可是直接应用DFS复杂度会很高,由于这道题咱们只要知道结尾就行了,不用继续往下搜。
因此问题就转化成怎样用DFS的同时又能够限制DFS的深度,因此咱们能够BFS与DFS结合。先用BFS搜到结尾字符串,而后把中途全部的字符串及其跟起始字符的edit distance存在一个map里。这样的话,咱们就能够从结尾字符串开始DFS,只有Map内的字符串才考虑继续DFS,直至搜到起始字符。
注意这里有个小技巧,就是为何不从起始字符串开始DFS直至搜到结尾字符串,而是反过来。这里能够脑子里想像一个图,若是从起始字符串开始搜,到最后一层的话会有不少无效搜索,由于那层咱们只须要找到结尾字符串,那么多无效的搜索到最一层太浪费时间。反之,若是咱们从结尾字符串开始DFS, 咱们把起始层控制在一个字符串,整个图先愈来愈宽,而后愈来愈窄直到起始字符串,而非一直愈来愈宽直到结尾字符串那层。
time: O(n), space: O(n)
public class Solution { public List<List<String>> findLadders(String beginWord, String endWord, Set<String> wordList) { Map<String, Integer> distMap = new HashMap<String, Integer>(); getDistance(beginWord, endWord, wordList, distMap); List<List<String>> res = new ArrayList<List<String>>(); dfs(res, new ArrayList<String>(), distMap, wordList, endWord, beginWord); return res; } public void dfs(List<List<String>> res, List<String> cur, Map<String, Integer> distMap, Set<String> wordList, String word, String des) { if (word.equals(des)) { List<String> list = new ArrayList<String>(cur); list.add(des); Collections.reverse(list); res.add(list); return; } cur.add(word); for (int i = 0; i < word.length(); i++) { char[] chars = word.toCharArray(); for (char c = 'a'; c <= 'z'; c++) { chars[i] = c; String nextWord = new String(chars); // 不只字典中含有,两字符串也是要在路径的相邻位置即距离差1 if (distMap.containsKey(nextWord) && distMap.get(nextWord) == distMap.get(word) - 1) { dfs(res, cur, distMap, wordList, nextWord, des); } } } cur.remove(cur.size() - 1); } // 用Word Ladder I的方法把候选字符串及其距离存入map,缩小DFS范围。 public void getDistance(String beginWord, String endWord, Set<String> wordList, Map<String, Integer> distMap) { distMap.put(beginWord, 1); Queue<String> q = new LinkedList<String>(); q.add(beginWord); while (!q.isEmpty()) { String word = q.remove(); for (int j = 0; j < word.length(); j++) { char[] chars = word.toCharArray(); for (char c = 'a'; c <= 'z'; c++) { chars[j] = c; String nextWord = new String(chars); if (nextWord.equals(endWord)) { distMap.put(nextWord, distMap.get(word) + 1); return; } if (wordList.contains(nextWord) && !distMap.containsKey(nextWord)) { distMap.put(nextWord, distMap.get(word) + 1); q.add(nextWord); } } } } } }