2018-10-02 23:46:38
问题描述:
问题求解:
显然是个解空间遍历问题,每次修改其中一位,由于步长是1,所以可以使用BFS进行解空间的遍历。
解法一、单向BFS
public int ladderLength(String beginWord, String endWord, List<String> wordList) { Set<String> set = new HashSet<>(); for(String i : wordList) set.add(i); if (!set.contains(endWord)) return 0; if (beginWord.equals(endWord)) return 1; Queue<String> queue = new LinkedList<>(); Set<String> used = new HashSet<>(); int step = 0; queue.add(beginWord); used.add(beginWord); while(!queue.isEmpty()) { int size = queue.size(); step++; for (int i = 0; i < size; i++) { char[] chs = queue.poll().toCharArray(); for (int j = 0; j < chs.length; j++) { char ch = chs[j]; for (char c = 'a'; c <= 'z'; c++) { if (c == ch) continue; chs[j] = c; String then = new String(chs); if (then.equals(endWord)) return step + 1; if (!set.contains(then) || used.contains(then)) continue; queue.add(then); used.add(then); } chs[j] = ch; } } } return 0; }
这里有个简单的优化,就是不使用used数组,而是每次使用扩展一个数前,将其从set中去除来防止再次扩展这个数。
public int ladderLength(String beginWord, String endWord, List<String> wordList) { Set<String> set = new HashSet<>(); for(String i : wordList) set.add(i); if (!set.contains(endWord)) return 0; if (beginWord.equals(endWord)) return 1; Queue<String> queue = new LinkedList<>(); int step = 0; queue.add(beginWord); while(!queue.isEmpty()) { int size = queue.size(); step++; for (int i = 0; i < size; i++) { char[] chs = queue.poll().toCharArray(); for (int j = 0; j < chs.length; j++) { char ch = chs[j]; for (char c = 'a'; c <= 'z'; c++) { if (c == ch) continue; chs[j] = c; String then = new String(chs); if (then.equals(endWord)) return step + 1; if (!set.contains(then)) continue; set.remove(then); queue.add(then); } chs[j] = ch; } } } return 0; }
解法二、双向BFS
单向的BFS是可以通过所有的用例的,但是本题中解空间还是比较庞大的,可以使用双向BFS来进一步的提高算法的时间复杂度。
从两边开始遍历,每次遍历一端,所以需要维护两个Set,这里不用Queue是为了方便实现。
public int ladderLength(String beginWord, String endWord, List<String> wordList) { Set<String> set = new HashSet<>(); for(String i : wordList) set.add(i); if (!set.contains(endWord)) return 0; if (beginWord.equals(endWord)) return 1; Set<String> q1 = new HashSet<>(); Set<String> q2 = new HashSet<>(); q1.add(beginWord); q2.add(endWord); int step = 0; while (!q1.isEmpty() && !q2.isEmpty()) { step++; if (q1.size() > q2.size()) { Set<String> tmp = q1; q1 = q2; q2 = tmp; } Set<String> cur = new HashSet<>(); for (String w : q1) { char[] chs = w.toCharArray(); for (int i = 0; i < chs.length; i++) { char ch = chs[i]; for (char c = 'a'; c <= 'z'; c++) { if (c == ch) continue; chs[i] = c; String then = new String(chs); if (q2.contains(then)) return step + 1; if (!set.contains(then)) continue; set.remove(then); cur.add(then); } chs[i] = ch; } } q1 = cur; } return 0; }