我有一套地图,比如说
a => {cow, dog}, b => {dog}
并希望将其作为范围地图存储到数组中,例如
a => (start: 0, end: 1), b => (start: 2, end: 2)
[cow, dog, dog]
当然除外
a => (start: 0, end: 1), b => (start: 1, end: 1)
[cow, dog]
将是一种更有效的表现形式。如何找到最小的解决方案?这让我觉得有些东西会被更多的人研究,但搜索会产生无穷无尽的相关内容。
答案 0 :(得分:0)
我对你的问题有一些非常不完整的想法,这些想法太长而无法形成评论。
在您的示例中,您的解决方案依赖于
这一事实P1 = {cow}
P2 = {dog}
是最小的不相交集,并且每个集都是这些集合的(不相交):
S1 = union(P1,P2)
S2 = P2
一个更复杂的例子可能会添加一只猪和一只鸭子,有三组
S1 = {cow,dog,pig}
S2 = {dog,pig}
S3 = {cow,duck}
相应的最小不相交集是
P1 = {cow}
P2 = {dog,pig}
P3 = {duck}
就哪个
而言S1 = union(P1,P2)
S2 = P2
S3 = union(P1,P3)
道具一般来说,任何有限集合C = {S1,S2,...}
的元素都可以细分为最小的不相交分区,这样集合中的每个集合都是一个不相交的集合。一些收集的元素。
证明所有元素的范围都是U = union(S : S in C)
。然后,对所有元素P_trivial = {{e} : e in U}
的完整分区就是这样一个(非最小的)不相交的分区。由于所有这些不相交分区的集合都是非空的,并且由于它们的大小是有限的,因此通过良好的排序原则存在一个(不一定是唯一的)具有最小尺寸的分区。
任务#1 计算这个最有效的不相交分区。建议的起点是找到每对集合的交集和补充,并从中构建。
现在有了一个有效的不相交的元素分区,每个集合的格式为
S_i = union(P_j : P_j in partition such that contains(i,j)
其中contains(i,j)
是二进制谓词,表明集合S_i
保留了分区集P_j
。您可以将contains(i,j)
视为形成一个矩阵,其行数等于集合数,列数等于分区数。在牛/狗的例子中,
contains = 1 1 0
0 1 0
1 0 1
请注意,此矩阵的两列不相等。如果列j1等于列j2,则集合将包括分区元素P_j1
< =>如果包含P_j2
,那么加入P_j1
和P_j2
将是一个更有效的分区。 (也许这是从平凡分区开始寻找最小分区的更好方法。)
两列内容越近,将相应的分区元素放在数组中就越有意义。 “close”的定义可以只是两列相等的行数(即包含或不包含这些分区元素的集合的数量)。这将导致很多关系,并且通过分区元素中的元素数量对此进行加权可能是有意义的。
将这个简单的距离度量(忽略权重)应用于列对会导致“接近”矩阵。对于牛/狗的例子,这将是
3 1 2
1 3 0
2 0 3
这个“接近度”矩阵的伪方程可能是
Closeness = Contains^T (&) Contains
即。矩阵乘法的一个版本。
如果分区元素“紧密”在一起,它们应该连续出现在数组中。对于这个给定的矩阵,这表示顺序
[P2 P1 P3] = [dog, pig, cow, duck]
就这个数组而言,
S1 = range 0 to 2
S2 = range 0 to 1
S3 = range 2 to 3
我通过选择矩阵中最大的非对角线条目来得到这个 - 2,对应于P1和P3,将它们粘在一起。然后,我看着P2是否更靠近P1或P3,并将它粘在它靠近的一侧。当然,我没有把它写成一个完整的算法或证明任何类型的最小化,但我相信它可能会概括:选择最大的非对角线元素,将两个相应的分区元素放在一起,然后链接剩余的分区任何一方的元素。