为什么我的BFS算法没有返回预期的最短路径?

时间:2018-04-18 05:32:43

标签: javascript algorithm breadth-first-search

我正在尝试编写一个算法,该算法应该找到从给定 beginWord endWord 的最短转换路径,这样一次就可以更改一个字母。

测试用例

beginWord = "hit"

endWord = "cog"

wordList = ["hot","dot","dog","lot","log","cog"]

预期输出为5,因为最短转换之一可以跟随其长度为5:

"hit" -> "hot" -> "dot" -> "dog" -> "cog"

在我的算法中,我使用队列跟踪BFS,并且对于每个单词,我将所有字母替换为所有字母,从' a'到' z'在这样做的同时,我检查给定字典中是否存在结果词,即 wordList

如果确实如此,那么我将它推入队列,因此它也可以像最后一个字一样进行处理。否则,将从队列中进行下一个条目,依此类推,直到队列为空。

现在,我在下面给出的代码返回hit -> hot -> dot -> lot -> dog -> log -> cog,这是一个错误的输出。这主要是因为dotlot以及dog的错误转换。

lotdog以及与dot不同的一个字母,因此它们都会被推送到队列并稍后处理,这会导致类似{{1}的双重转换问题进入lotlog

现在,这清楚地表明我错过了BFS和最短路径搜寻的一些关键点。我如何确定必须将cog转换为dot而不是dog,以确保我按照最短路径到达预期目标,前提是两者都是有效转换lot

这有助于我理解和修复我的代码。

dot

3 个答案:

答案 0 :(得分:0)

您可以在转换字符串时执行一些额外的处理以获得正确的输出。在替换字母之前,将要替换的字符(i)与将其放置的字符(j)进行比较。

为每次迭代保留一个标志变量flag,并检查新字符j是否更接近EndWord中相应位置的字符。如果它靠近而不是离开(例如,对于cog中的'c','d'对'l')并存在于WordList中,请进行替换并设置flag = true。如果距离角色的距离相同也可以进行另一次变换,请检查标志,如果为真,则跳过它,否则进行变换。

希望这有帮助。

答案 1 :(得分:0)

  

我用所有字母替换每个字母


意味着您进行了太多有效性检查。
我建议您只用有效字母替换每个字母。例如,“hit”中的i只能替换为o:“hot”,“dot”,“dog”,“lot”,“log”,“cog”。
这将使程序更高效,更不容易出错。

答案 2 :(得分:0)

我想我在理解中找到了主要问题。主要问题是在给定的水平,即距离' d'从树的根级,我可以有多个匹配,例如"批号"和#34;狗"通过转换" dot"来达到与它们相同的水平。

在每个级别,我必须耗尽队列,否则我计算的距离将变得不正确。

因此,当我将代码更改为以下代码(请参阅代码中的注释Process all items in queue which contains words on same level)时,算法变得更好。至少对于许多测试案例更好,包括在这个问题中给出的测试案例。

感谢大家审核代码。 :)

var ladderLength = function(beginWord,endWord,wordList){         wordList = new Set(wordList);

    var queue = [], distance = 1, i, j, len;
    len = beginWord.length;
    queue.push(beginWord);

    while (queue.length > 0) {
        // Process all items in queue which contains words on same level
        for (var k=0; k<queue.length; k++) {
            var currentWord = queue.shift();
            if (currentWord === endWord) {
                return distance;
            }

            for (i = 0; i < len; i++) {
                var tempCh = currentWord[i];
                for (j = 'a'; j <= 'z'; j = String.fromCharCode(j.charCodeAt(0)+1)) {
                    if (j !== tempCh) {
                        currentWord = currentWord.replaceAt(i,j);
                        if (wordList.has(currentWord)) {
                            wordList.delete(currentWord);
                            queue.push(currentWord);
                        }
                    }
                }
                currentWord = currentWord.replaceAt(i, tempCh);

            } 
        }
        distance++;
    }
    return 0;
};

String.prototype.replaceAt=function(index, replacement) {
    return this.substr(0, index) + replacement+ this.substr(index + replacement.length);
}