假设我有以下列表:
[1, 2, 3, 20, 23, 24, 25, 32, 31, 30, 29]
[1, 2, 3, 20, 23, 28, 29]
[1, 2, 3, 20, 21, 22]
[1, 2, 3, 14, 15, 16]
[16, 17, 18]
[16, 17, 18, 19, 20]
订单在这里很重要。这些是由加权图中的深度优先搜索产生的节点。我想要做的是将列表分解为唯一路径(路径至少有2个元素)。因此,上面的列表将返回以下内容:
[1, 2, 3]
[20, 23]
[24, 25, 32, 31, 30, 29]
[28, 29]
[20, 21, 22]
[14, 15, 16]
[16, 17, 18]
[19, 20]
我现在的一般想法是:
查看所有列表对,在列表开头创建一组重叠段列表。例如,在上面的例子中,这将是输出:
[1, 2, 3, 20, 23]
[1, 2, 3, 20]
[1, 2, 3]
[16, 17, 18]
下一个输出是这样的:
[1, 2, 3]
[16, 17, 18]
一旦我获得了步骤2中的列表,我会查看每个输入列表,如果它与步骤2中的一个列表匹配,则会切断前面的列表。新列表如下所示:
[20, 23, 24, 25, 32, 31, 30, 29]
[20, 23, 28, 29]
[20, 21, 22]
[14, 15, 16]
[19, 20]
然后我返回并将步骤1应用于步骤3中的截断列表。当步骤1未输出任何重叠列表时,我已完成。
第2步是这里棘手的部分。愚蠢的是它实际上等同于解决原始问题,尽管在较小的列表上。
解决此问题的最有效方法是什么?查看所有对显然需要O(N ^ 2)时间,并且步骤2看起来很浪费,因为我需要运行相同的过程来解决这些较小的列表。我试图弄清楚是否有更聪明的方法来做到这一点,而且我被卡住了。
答案 0 :(得分:1)
似乎解决方案是修改Trie以达到目的。 Trie压缩提供了线索,但这里所需的压缩类型不会产生任何性能优势。
您添加的第一个列表将成为它自己的节点(而不是k个节点)。如果有任何重叠,节点会分裂,但永远不会小于保持数组的两个元素。
图结构的一个简单示例如下所示:
insert (1,2,3,4,5)
graph: (1,2,3,4,5)->None
insert (1,2,3)
graph: (1,2,3)->(4,5), (4,5)->None
insert (3,2,3)
graph: (1,2,3)->(4,5), (4,5)->None, (3,32)->None
segments
output: (1,2,3), (4,5), (3,32)
子节点也应该作为一个实际的Trie添加,至少当它们足够多时,为了避免在数据结构中添加/删除时的线性搜索,并可能将运行时间增加N倍。如果是实现后,数据结构具有与Trie相同的大O性能,隐藏常数稍高。这意味着它需要O(L * N),其中L是列表的平均大小,N是列表的数量。获得段是段数的线性。
对于您的示例,最终的数据结构(基本上是有向图)如下所示,起始节点位于底部。
请注意,此数据结构可以在运行DFS而不是后缀时构建。
答案 1 :(得分:0)
我最后通过略微区别地思考问题来解决这个问题。我没有考虑节点序列(每个连续节点对之间隐含边缘),而是考虑边缘序列。我基本上使用我最初发布的算法。步骤2只是一个迭代步骤,我重复识别前缀,直到没有剩余的前缀来识别。这很快,处理边缘而不是节点真的简化了一切。
感谢大家的帮助!