寻求保留重复的合并算法

时间:2015-05-05 04:23:02

标签: algorithm merge duplicates

我需要一种算法来进行一些不寻常的合并。我确信我可以创建一个,但我怀疑有不止一种方法可以做到这一点,而且我不确定我创建的算法是否最好。我想知道一个设计良好的人是否已经知道。

在以下示例中,诸如tree,duck,hat,...之类的单词表示任意类型的对象。它们可以是单词,记录,消息等。下标(L)和(R)代表原点("左"或"右")。树(L)和树(R)根据定义是相同的,除了它们出现的来源。

在结果中,' ==='手段"相当于。"例如,"树(L)=== tree(R)"意味着"树"左边的来源相当于" tree"在正确的来源。 "鸭(L)==="意味着" duck"在左边的源中没有相应的来源。 " ===太阳(R)"意味着" sun"在右边的来源中,左边的来源没有等价物。

鉴于这些来源,算法会产生以下结果:

Left:   tree(L), duck(L), hat(L), peg(L)
Right:  tree(R), hat(R), sun(R), peg(R)
Result: tree(L)===tree(R), duck(L)===, hat(L)===hat(R), ===sun(R), peg(L)===peg(R)

顺序是重要的,并且给出了一个选择,算法在最靠近左边开头的对象的右边源中找到一个等价物:

Left:   tree(L), duck(L), peg(L), hat(L)
Right:  tree(R), hat(R), peg(R)
Result: tree(L)===tree(R), duck(L)===, ===hat(R), peg(L)===peg(R), hat(L)
Not:    tree(L)===tree(R), duck(L)===, peg(L)===, hat(L)===hat(R), ===peg(R)

任何数量的对象可能在一个源中连续出现而在另一个源中不会出现,因此简单的前瞻方法不会起作用:

Left:   tree(L), wig(L), yolk(L)
Right:  tree(R), cap(R), jet(R), map(R), fox(R),... ink(R), yolk(R)
Result: tree(L)===tree(R), wig(L)===, ===cap(R), ===jet(R), ===map(R), ===fox(R),... ===ink(R), yolk(L)===yolk(R)

现在奇怪的部分:算法必须保留重复:

Left:   tree(L), rim(L), lamp(L)
Right:  tree(R), rim(R), rim(R), lamp(R)
Result: tree(L)===tree(R), rim(L)===rim(R), ===rim(R), lamp(L)===lamp(R)

有没有人知道这种方式设计良好的算法?

1 个答案:

答案 0 :(得分:0)

如果我理解正确的问题,那么你正在寻找某种贪心算法。 以下示例说明了为什么流程贪婪,但也注定要看我是否理解正确的问题。

Left:   A B C D E F G H I J
Right:  A J C D E F G H I
Result: A=A B= C= D= E= F= G= H= I= J=J =C =D =E =F =G =H =I

J(L)元素需要与J(R)元素一起映射("算法在最靠近左边开头的对象的右边源中找到一个等价物"),因此,所有其他可能的匹配都不再可能。

此答案尚未提供您的问题的答案,请确认示例解决方案是正确的。

此外,尚不清楚合并应该如何进行:

Left:          A B C D E F
Right:         A G H I J F
Possibility 1: A=A B= C= D= E= =G =H =I =J F=F
Possibility 2: A=A =G =H =I =J B= C= D= E= F=F
Possibility 3: A=A B= =G C= =H D= =I E= =J F=F
... many other possibilities

我不认为这种特定的算法已经存在。

根据输入大小,简单的O(n ^ 2)算法最简单,但如果输入大小太大,可能需要更好的算法。

对于右侧列表中的每个条目,扫描左侧列表中是否存在匹配条目,仅扫描最​​后一个匹配元素的条目。 如果找到这样的条目,则可以将其与右侧列表中的元素匹配(在将所有先前的剩余条目插入为不匹配之后)。如果未找到匹配的元素,请将右侧列表中的元素作为不匹配项插入,并继续使用下一个元素。

这可以简单地用三个指针实现:右列表中的当前元素,左列表中的最后匹配元素和左列表中当前搜索的元素(始终从最后匹配元素到列表末尾,除非匹配元素更快找到)。