原题地址:
https://leetcode.com/problems/word-ladder/description/
题目:
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:
- Only one letter can be changed at a time.
- Each transformed word must exist in the word list. Note that beginWord is not a transformed word.
For example,
Given:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log","cog"]
As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog"
,
return its length 5
.
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.
解法:
这道题目给定一个开始的单词和一个结束的单词,然后给了一个单词的数组,每次能变换单词的一个字母,要求由开始单词变换到结束单词的最短路径的长度。看似是字符串的题目,但涉及到最短路径,就知道是使用BFS进行解决。
准备一个队列,先把开始单词放进队列里面,每次从队列中拿出一个单词,我们把它称为“当前单词”。当“当前单词”与结束单词一样时,返回当前遍历到的层数。否则,把搜索到与当前单词相差一个字母的单词放进队列里面。每次把一个单词放进队列里面时,把这个单词从单词数组里面删除掉,以防形成环路。
具体实现代码如下:
class Solution { public: bool isConnected(string a, string b) { int num = 0; for (int i = 0; i < a.size(); i++) { if (a[i] != b[i]) num++; } return num == 1; } int ladderLength(string beginWord, string endWord, vector<string>& wordList) { int res = 1; queue<string> q; q.push(beginWord); int count = 1; while (!q.empty()) { string str = q.front(); q.pop(); count--; if (str == endWord) return res; for (vector<string>::iterator iter = wordList.begin(); iter != wordList.end();) { if (isConnected(str, *iter)) { q.push(*iter); iter = wordList.erase(iter); } else { iter++; } } if (count == 0) { count = q.size(); res++; } } return 0; } };
上面的代码有两点值得去研究的:
(1)
count变量的使用:这是用来计算当前层数的,每当count为0,表明已经把一层的单词都访问过了,层数res加1,然后再把新的一层的单词个数赋给count。这是需要理解一下的地方。
(2)
把单词放进队列时,要把这个单词从原来的数组里面erase掉,避免出现环路。但现在erase掉的单词,为什么就不会在后面使用到呢(不同的路径)?这个我刚做完的时候百思不得其解,后来一想,假如后面使用到了,它也不会是最短的路径(使用到的那一条路径的后半部分和当前路径一模一样),因此可以直接erase掉。