LeetCode 127. Word Ladder 单词接龙(Java)

题目:

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:

  1. Only one letter can be changed at a time.
  2. Each transformed word must exist in the word list.

Note:

  • Return 0 if there is no such transformation sequence.
  • All words have the same length.
  • All words contain only lowercase alphabetic characters.
  • You may assume no duplicates in the word list.
  • You may assume beginWord and endWord are non-empty and are not the same.

Example 1:
Input:
beginWord = “hit”,
endWord = “cog”,
wordList = [“hot”,“dot”,“dog”,“lot”,“log”,“cog”]
Output: 5
Explanation: As one shortest transformation is “hit” -> “hot” -> “dot” -> “dog” -> “cog”,
return its length 5.

Example 2:
Input:
beginWord = “hit”
endWord = “cog”
wordList = [“hot”,“dot”,“dog”,“lot”,“log”]
Output: 0
Explanation: The endWord “cog” is not in wordList, therefore no possible transformation.

解答:

这道题用到了图的相关知识。第一次接触图相关题目,一开始没有采用图的数据结构,所以解题思路一直有错误。

这是一道单源头广度优先搜索最短路径,需要结合图的知识。

首先构建图。图的定点就是每个单词,若顶点的两个单词之间只相差一个字母,则这两个顶点构成一条边。以题中例1为例,图为下图所示:
LeetCode 127. Word Ladder 单词接龙(Java)_第1张图片
题目即可以理解为:给定一个初始节点 beginWord,一个终止节点 endWord,寻找从 beginWord 到 endWord 的所有路径中,最少包含多少个节点。
搜索问题可以用 DFS 和 BFS 解决,DFS更适合搜索有多少条路径,BFS更适合搜索最小深度,即本题采用图的广度优先搜索。

具体的解题思路如下:

  1. 创建 HashSet 替换题目中存储单词的List,便于后续搜索,可以快速判断是否存在相应单词

  2. 创建 HashMap,存储寻找到的路径中,已访问过的节点及对应的路径值

  3. 借助队列来进行广度优先遍历
    创建一个队列,将源顶点加入队列。若队列不为空,则逐个取出队列中的顶点寻找邻接节点并判断。若存在邻接节点等于 endWord,则直接返回路径值+1;若邻接节点存在于字典,且未被访问过,则标记为"已访问",并加入 queue

    其中,寻找邻接节点采用了暴力方法,即依次将节点单词的每个位换成其他25个字母,判断是否存在于给定的字典中。

class Solution {
    public int ladderLength(String beginWord, String endWord, List<String> wordList) {
        HashSet<String> wordSet = new HashSet<>(wordList);
        //若字典中不存在 endWord,则不包含路径,直接返回0
        if(!wordSet.contains(endWord)) {
            return 0;
        }
        //存储已访问的节点,并存储其在路径上的位置
        HashMap<String, Integer> map = new HashMap<>();
        //添加源顶点为“已访问”,并记录它在路径的位置
        map.put(beginWord, 1);
        Queue<String> queue = new LinkedList<>();
        queue.add(beginWord);
        while(!queue.isEmpty()) {
            String word = queue.poll();
            int level = map.get(word);
            for(int i=0; i<word.length(); i++) {
                char[] wordArray = word.toCharArray();                
                for(char j='a'; j<='z'; j++) {
                    if(wordArray[i] == j) {
                        continue;
                    }
                    wordArray[i] = j;	//对于每一位字母,分别替换成另外25个字母
                    String check = new String(wordArray);
                    if(check.equals(endWord)) {
                        return level + 1;
                    }
                    //如果字典中存在邻接节点,且这个邻接节点还未被访问
                    if(wordSet.contains(check) && !map.containsKey(check)) {
                        map.put(check, level+1);
                        queue.add(check);
                    }
                }
            }
        }
        return 0;
    }
}

你可能感兴趣的:(LeetCode)