一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情
题目(Word Ladder)
链接:https://leetcode-cn.com/problems/word-ladder
解决数:764
通过率:47.4%
标签:广度优先搜索 哈希表 字符串
相关公司:amazon facebook google
字典 wordList 中从单词 beginWord **和 endWord 的 转换序列 是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> ... -> sk:
- 每一对相邻的单词只差一个字母。
- 对于
1 <= i <= k时,每个si都在wordList中。注意,beginWord**不需要在wordList中。 sk == endWord
给你两个单词 **beginWord **和 endWord 和一个字典 wordList ,返回 从 beginWord 到 endWord 的 最短转换序列 中的 单词数目 。如果不存在这样的转换序列,返回 0 。
示例 1:
输入: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"]
输出: 5
解释: 一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog", 返回它的长度 5。
示例 2:
输入: beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log"]
输出: 0
解释: endWord "cog" 不在字典中,所以无法进行转换。
提示:
1 <= beginWord.length <= 10endWord.length == beginWord.length1 <= wordList.length <= 5000wordList[i].length == beginWord.lengthbeginWord、endWord和wordList[i]由小写英文字母组成beginWord != endWordwordList中的所有字符串 互不相同
思路
bfs,循环beginWord,对每个字符替换26个小写字符,看新生成的单词是否在wordList里面,如果存在就是一个合法的路径,直到新生成的单词是endWord,循环完成还是没到达endWord就返回0。双向bfs思路一样,只不过是从两边向中间靠拢,判断新生成的单词是否在另一个方向走过的路径中。
方法1:bfs
js:
const ladderLength = (beginWord, endWord, wordList) => {
const wordSet = new Set(wordList);
const queue = [];
queue.push([beginWord, 1]);//开始单词和层级加入队列
while (queue.length) {
const [word, level] = queue.shift()//出队 进行bfs
if (word == endWord) {//和endword相等返回层级
return level;
}
for (let i = 0; i < word.length; i++) { //循环单词列表
for (let c = 97; c <= 122; c++) { //循环26个小写字符
//得到新的单词
const newWord = word.slice(0, i) + String.fromCharCode(c) + word.slice(i + 1);
if (wordSet.has(newWord)) { //检查wordset包不包括新生成的单词 避重复入列
queue.push([newWord, level + 1]); //新单词加入队列
wordSet.delete(newWord); //避死循环
}
}
}
}
return 0; // bfs结束,始终没有遇到终点
};
方法2:双向bfs
js:
var ladderLength = function(beginWord, endWord, wordList) {
let wordSet = new Set(wordList)
if (!wordSet.has(endWord)) return 0
//从beginWord到endWord
let begSet = []
//从endWord到beginWord
let endSet = []
begSet.push(beginWord)
endSet.push(endWord)
let n = 1//层级
while(begSet.length > 0){//开始遍历单词
const nextBegins = []//bfs下一层级的单词数组
//步数少数对换一下,让走的慢的在走几步
if(begSet.length > endSet.length){
let q = begSet
begSet = endSet
endSet = q
}
//循环begSet
for(let k = 0; k < begSet.length;k++){
let m = begSet[k]
for(let i = 0; i < m.length; i++){
for (let c = 97; c <= 122; c++){
//生成新词
let newm = m.slice(0, i) + String.fromCharCode(c) + m.slice(i + 1);
if(endSet.includes(newm)){//相遇
return n + 1
}
if( wordSet.has(newm)){
nextBegins.push(newm) //下一层bfs的单词数组
wordSet.delete(newm) //防止重复
}
}
}
}
begSet = nextBegins
n++ //层级+1
}
return 0
};