我想将数组与common元素合并。我有这样的数组列表:
List<int[]> arrList = new List<int[]>
{
new int[] { 1, 2 },
new int[] { 3, 4, 5 },
new int[] { 2, 7 },
new int[] { 8, 9 },
new int[] { 10, 11, 12 },
new int[] { 3, 9, 13 }
};
我想合并这些数组:
List<int[]> arrList2 = new List<int[]>
{
new int[] { 1, 2, 7 },
new int[] { 10, 11, 12 },
new int[] { 3, 4, 5, 8, 9, 13 } //order of elements doesn't matter
};
怎么做?
答案 0 :(得分:4)
让每个数字成为标记图形中的顶点。对于每个数组,连接给定数组中的数字所指向的顶点。例如。给定数组(1,5,3)创建两个边(1,5)和(5,3)。然后找到图表中的所有连接组件(请参阅:http://en.wikipedia.org/wiki/Connected_component_(graph_theory))
答案 1 :(得分:1)
使用Disjoint-Set Forest data structure。数据结构支持三种操作:
MakeSet(item
) - 创建一个包含单个项目的新集Find(item)
- 给定一个项目,查找一个集合。Union(item1, item2)
- 给定两个项目,将它们所属的集合连接在一起。您可以浏览每个数组,并在其第一个元素和您之后找到的每个元素上调用Union
。完成列表中的所有数组后,您将能够通过再次遍历所有数字并在其上调用Find(item)
来检索各个集合。生成相同集合的Find
的数字应该放在同一个数组中。
此方法在O(α(n))
摊销中完成合并(α
增长非常缓慢,因此出于所有实际目的,它可以被视为一个小常数。)
答案 2 :(得分:1)
我非常确定它不是最好和最快的解决方案,但有效。
static List<List<int>> Merge(List<List<int>> source)
{
var merged = 0;
do
{
merged = 0;
var results = new List<List<int>>();
foreach (var l in source)
{
var i = results.FirstOrDefault(x => x.Intersect(l).Any());
if (i != null)
{
i.AddRange(l);
merged++;
}
else
{
results.Add(l.ToList());
}
}
source = results.Select(x => x.Distinct().ToList()).ToList();
}
while (merged > 0);
return source;
}
我使用List<List<int>>
代替List<int[]>
来获取AddRange
方法。
用法:
var results = Merge(arrList.Select(x => x.ToList()).ToList());
// to get List<int[]> instead of List<List<int>>
var array = results.Select(x => x.ToArray()).ToList();