寻找最小数量的转换

时间:2009-09-08 01:26:02

标签: algorithm math

我需要一种计算类似于Levenshtein距离的算法。它应该计算从一个序列到另一个序列的最小可能转换次数。允许的转换是删除,插入和移动:

删除3: {1,2,3,4}之前,{1,2,4}之后

插入5: 在{1,2,3,4,4}

之后的{1,2,3,4}之前

移动4: {1,2,3,4}之前,{4,1,2,3}之后

因此,算法应该在给定数字的起始和结束序列的情况下计算这种变换的最小数量,并且理想地,给出所需变换的列表。序列的一个重要特征是数字永远不会重复。

我有一个想法,我可以修改Levenshtein算法,因此它只计算删除和插入的数量,并忽略替换。移动次数将是删除次数加上插入次数除以2.但我不确定它是否正确。

有人知道这样的算法吗?

修改

我可能应该说,这个算法适用于一系列序列。例如:

{{1,2,3},{4},{5,6,7}}

其中数字不重复。序列中内部元素的总数不会更改。元素可以从一个内部序列迁移到另一个内部序列。内序列的数量也是不变的。所以它可能是

{{1,2,3,4,5,6,7},{},{}}
{{},{1,2,3,4,5,6,7},{}}
{{},{},{1,2,3,4,5,6,7}}

想法是计算每个相应内部序列的距离,然后将它们相加以获得外部序列的距离 因此,元素可以删除或插入到内部序列中,但它们永远不会从外部序列中消失。

此算法最重要的方面是它应该找到 MINIMAL 转换次数。不只是一些转化。

5 个答案:

答案 0 :(得分:2)

您可以跟踪已删除和插入的数字,最后通过检查这两组来查找已删除并重新插入的数字来计算移动次数:

moved = intersection(deleted, inserted)
moves = sizeof(moved)
deletions = sizeof(deleted) - sizeof(moved)
insertions = sizeof(inserted) - sizeof(moved)

答案 1 :(得分:1)

由于您的列表仅包含唯一元素,因此您必须清除哪些必须删除以及必须插入哪些元素。剩下的问题是从一个列表开始找到包含相同元素的另一个列表所需的最小移动数。始终可以重新标记两个列表中的元素,使得凝视列表中的元素不断增加。

E.g。我们可能会遇到问题,从列表中找到最小数量的移动

  

[1,2,3,4,5,6,7]

给出了列表

  

[3,5,1,2,4,7,6]。

要解决这个问题,可以使用一点技巧。不是试图找到要移动的最小数量的元素,而是更容易找到不需要移动的最大数量的元素。这些必须是第二个列表中按升序排列的元素。 这是longest increasing subsequence problem。 在上面的例子中,1,2,4,7例如是最大子集。因此,要移动的最小元素集将是{3,5,6}。

答案 2 :(得分:0)

考虑:

abc

转换为:

abcdef

这是3次插入,0次删除和0次移动。但是,您的算法将提供3次插入,0次删除和1.5次移动。

答案 3 :(得分:0)

让我们看看我是否正确理解了你的问题:你已经给出了一个序列X(可能是空的)序列,其中从1到n的每个数字都包含在一个(内部)序列中。只使用两种类型的操作,您必须将X转换为另一个给定的相同类型的序列Y,您希望最小化转换所需的操作数。

第一个操作是将数字从任何位置移动到同一内部序列中的任何其他位置。第二个操作是将一个数字从一个内部序列中的任何位置移动到另一个内部序列中的任何位置。

这是你的问题吗?如果是,请继续阅读。

解决这个问题的一般方法是考虑通过将与X和Y相同类型的所有序列作为顶点集给出的无序图。两个顶点通过图中的边连接,当且仅当它们可以使用两个允许的操作中的一个进行相互转换时(这种关系是对称的,因为您可以通过另一个允许的操作撤消允许的操作)。现在使用最短路径查找算法,例如breadth first search,其中动态生成邻居。

随着可到达顶点的数量在所采取的步数中大致呈指数增长,实际上您应该从起点X和起点Y交替运行算法。只要所有顶点都可以在1,2中到达,就切换起点,3,...步骤确定,当你从X rsp获得可到达的点集时停止。 Y相交。

这种通用算法的运行时间和内存使用量对于中等n来说太高了,但是可以使用两个观察值进行极大优化:

  • 从一开始就按正确顺序包含的元素可以使用所有其他元素(即包含在其他内部序列中的那些元素或那些元素中的第一个独立操作)必须转移到另一个内部序列。)

  • 通过第二次操作从一个内部序列移动到另一个内部序列的元素可以直接放入正确内部序列中的正确位置,这样就不必再通过其他操作再次移动它们。

由于内部序列内的排序和内部序列之间元素的移动都是独立的,因此操作总数是对内部序列进行排序的最小数量的总和(仅限于同一内部序列中的元素)必须考虑X和Y)以及必须从一个内部序列移动到另一个内部序列的元素数量。

要确定对内部序列中已正确包含的元素进行排序的(第一个)操作的数量,只需忽略(取消)必须移动到另一个内部序列的元素。然后对图形使用上面描述的通用方法,顶点是由不要移动的元素组成的序列集。如果移动元素(即应用第一个操作)将一个顶点(=序列)转换为另一个顶点(=序列),则图中存在两个顶点。

答案 4 :(得分:0)

我认为可以简化为:

  1. 忽略不属于此序列的元素,重新排列按正确顺序排列的元素。这是一个简单但不寻常的排序问题。
  2. 删除不需要的元素。
  3. 插入缺失的元素(在正确的位置)。

最低限度地做第一步是棘手的​​部分;我不清楚如何证明给定的移动顺序是最小的。但是,由于您似乎并不关心计算成本,因此您可以做一些接近蛮力搜索的事情(例如,使用快速排序作为上限)。