我应该如何修改此Java代码,以便保存所有可能的路径?

时间:2018-08-20 09:28:43

标签: java

我需要Java代码,该代码选择两个单词之间的最短路径,每个步骤仅更改一个字母。我只能实现以最短路径返回的代码。

1 个答案:

答案 0 :(得分:2)

问题重述

在此问题中,使用了查找功能(注:名称“查找”似乎没有 适当的。更好地使用findPath,恕我直言)从 存储在字符串列表中的单词字典。样本字典文本文件 可以在问题中找到下面的示例。

findPath函数采用三个参数:

  • 起始词
  • 目标词
  • 字典(单词列表)。

find函数尝试将起始单词“连接”到目标 通过由不同的“步骤”(即不同的) 全部属于字典的单词,但每个单词仅相差一个 前一个单词的字母。

例如

>>> find('hide', 'seek', words)
['hide', 'bide', 'bids', 'beds', 'bees', 'sees', 'seek']

这是一个由7个单词组成的6步路径。

当前实现只在所有可能的最短路径中产生一条路径 连接两个单词的路径,如果不存在,则为“无”。问题是 然后:

我应该如何修改它以产生一个列表的所有可能路径的列表 一定的长度,因为没有单词应该只连接一次 有效路径?

当前算法分析

将通过图形类比描述该算法。 该算法将“访问过的”字典构建为以 “无”,转到“开始”一词,然后从“开始”一词分支到每个 可以连接的单词。

然后通过检查每个新添加的单个节点(“ curr” 字符串),按照添加到树中的顺序。该算法跟踪 “队列”列表中包含在树中的单词,以便 如果再次遇到一个单词,将不再考虑。

将“目标”一词添加到树上之后,什么也不会发生,这是 小可惜。必须等待“目标”一词被检查,才能 检测到已找到路径。

检查“目标”字词后,便会快速返回路径 只需浏览树的根即可获得一种优雅的方式

    if curr == target:
        path = []
        while curr:
            path.insert(0, curr)
            curr = visited[curr]
        return path

当前算法属性

在当前形式和示例字典中,以 “无->线索”具有以下分支:

bead dead head mead read load lend leud lewd leaf leak leal lean leap lear leas

请注意,当前算法返回的路径是函数 单词被考虑的顺序,基本上是 字典中的单词和给定参数的顺序。因此, 如评论中所述,当前算法能够找到一个 或两个最短路径,因为我们可以反转参数的顺序,例如

>>> find("hide", "seek", words))
['hide', 'bide', 'bids', 'beds', 'bees', 'sees', 'seek'] 

但是

>>> find("seek", "hide", words)
['seek', 'meek', 'merk', 'mirk', 'mire', 'hire', 'hide'] 

以便可以立即找到hide-> hire-> mire-> mirk-> merk-> meek-> seek 作为替代的最短路径。

问题分析

您提出的问题有两个创新层次。首先, 算法应涵盖所有可能的最短路径,而不仅仅是第一条路径 被发现。其次,该算法应增加一个数字“ n” 并返回所有长度为“ n”的可能路径。

覆盖所有可能的最短路径

最短的路径(如果存在)至少有这么多 两个单词中字母不同的步数。

假设您要将“ lead”连接到“ heal”。有两个字母 差异,可能的最短路径是'lead-> head-> heal'。如果“头”是 词典中缺少“ leal”,然后是另一个最短的 路径将是“ lead-> leal-> heal”。如果“头”和“里”都丢失了, 最短路径将大于2。

通常,如果您加扰字典(更改顺序 的话),您应该可以获得不同的最短路径 使用相同的算法。但是为了确保获得所有可能的路径, 您应该执行大量的加扰操作 在我看来效率低下。

覆盖所有可能的路径

假设您要将“ lead”连接到“ heal”。可能最短 路径是“ lead-> head-> heal”。

如果您想考虑所有可能的路径, 您还必须考虑'lead-> dead-> head-> heal','lead-> read-> head-> heal', 'lead-> dead-> read-> head-> heal'等,在某些情况下, 与其他路径具有相同的词内容,但部分置换的顺序与 'lead-> read-> dead-> head-> heal'

结论

很明显,当前的树结构不适合描述所有 可能的路径,因为在树结构中单个节点是 一侧与其父级不对称连接,另一侧不对称 和他所有的孩子在一起。这种不对称性防止了任何可能性 考虑所有可能的路径,除非您准备复制 树很多次(但我不建议这样做) 所有可能存在的树木。

建议

1)将您的问题分为两个不同的步骤,第一步是“覆盖所有 可能的最短路径”,第二个“覆盖所有长度为n的可能路径”。 攻击最简单的问题并考虑第二个问题来解决它,即 不接受与第二个问题不兼容的解决方案。

2)将字典的大小减小到您选择的十几个单词,以便 为您提供了快速测试算法的可能性。例如

heal
head
leal
real
seal
lead
read
some
more
word    

允许您测试是否可以找到之间的两条最短路径 “领导”和“治愈”。

3)改变数据结构。留下被访问的字典及其树, 并改用其他数据结构。我建议使用清单清单 涵盖所有可能的最短路径,即在上面的示例中 成为每个可能路径的一个不同列表

[lead, leal]
[lead, head]
[lead, read]

[lead, leal, real]
[lead, leal, seal]
[lead, leal, heal] *solution*
[lead, head, read] 
[lead, head, heal] *solution*

4)建立一个可靠的测试平台:自己确定什么是 给定问题的预期输出,并在测试之前处理代码 成功。只有这样,才能使测试复杂化并再次调试代码。