携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第24天,点击查看活动详情
单词接龙
字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> ... -> sk:
每一对相邻的单词只差一个字母。 对于 1 <= i <= k 时,每个 si 都在 wordList 中。注意, beginWord 不需要在 wordList 中。 sk == endWord 给你两个单词 beginWord 和 endWord 和一个字典 wordList ,返回 从 beginWord 到 endWord 的 最短转换序列 中的 单词数目 。如果不存在这样的转换序列,返回 0 。
来源:力扣(LeetCode) 链接:leetcode.cn/problems/wo…
分析
常规BFS
- 这道题有点像之前写过的最小基因变化,只不过最小基因变化元素的每一位上有4种可能,单词接龙中的元素每一位上有26种可能,首先看起始单词和结束单词是否在单词库,如果有不存在的,返回0,如果都在,遍历起始单词的每一个字母,变化一位之后看是否在单词库里,如果有长度加一,如果没有返回0,同事记录当前的变化,中间如果有单词没有在单词库中,返回0,一直变化到结束单词,次数就是题目的答案
代码
var ladderLength = function(beginWord, endWord, wordList) {
let wordSet = new Set(wordList)
let q = [beginWord]
let level = 1
while(q.length){
let lsize = q.length
while(lsize-- > 0){
let word = q.shift()
if(word === endWord) return level
for(let i=0; i<word.length; i++){
for(let j=0; j<26; j++){
let newWord = word.slice(0, i) + String.fromCharCode(j+97) + word.slice(i+1)
if(wordSet.has(newWord)){
wordSet.delete(newWord);
q.push(newWord)
}
}
}
}
level++
}
return 0
};
双向BFS
- 假如每个节点的分支数量相同,搜索空间会随着层数的增长指数级增加,如果每层都是满二叉树扩展,节点的数量就是以2为底数的指数式增长,何况单词接龙每个位置上有26中可能。因此,可以使用两个同时进行的BFS减少搜索空间,一个从起始单词开始,一个从结束单词开始,当某一时刻,两个BFS访问了同一个节点就停止搜索
代码
var ladderLength = function(beginWord, endWord, wordList) {
const charMap = buildCharMap()
const wordSet = new Set(wordList)
if (!wordSet.has(endWord)) return 0
let leftSet = new Set([beginWord]), rightSet = new Set([endWord]), level = 1
const helper = (set1, set2) => {
const setArr = Array.from(set1)
for (let i = 0; i < setArr.length; i++) {
const word = setArr[i]
for (let i = 0; i < word.length; i++) {
for (const c of charMap) {
const newWord = word.slice(0, i) + c + word.slice(i + 1)
if (set2.has(newWord)) return true
if (wordSet.has(newWord)) {
set1.add(newWord)
wordSet.delete(newWord)
}
}
}
set1.delete(word)
}
}
while (leftSet.size && rightSet.size) {
level++
if (helper(leftSet, rightSet)) return level
level++
if (helper(rightSet, leftSet)) return level
}
return 0
};
const buildCharMap = () => {
const map = []
for (let i = 0; i < 26; i++) {
map.push(String.fromCharCode(i + 97))
}
return map
}
总结
- 本题是基于最小基因变化的基础上的扩展,当每个位置都有26种可能的时候,可以一个方向搜索,为了优化搜索空间,可以选择使用双向BFS来有效减少搜索空间
- 今天也有是有收获的一天