【发布时间】:2017-05-13 21:49:27
【问题描述】:
我见过几个处理类似问题的问题,但我尝试过的问题都不能满足我的特定需求,即使我尝试调整它们。
所以我有一组自定义对象,其中包含 1 到 30 个对象。其中许多对象都是相同的(我只有 8 种类型的对象),并且无法假设每种对象会有多少,有些类型可能不会全部存在。
我需要获取可以用我的集合制作的对象类型的所有组合(无序),这些对象的大小在特定范围内。这意味着我有一个最小值和最大值,我需要得到所有 asize 大于或等于最小值,并且小于或等于最大值的子集。
这很容易做到,只需使用提供所有子集的众多算法之一,然后删除不适合该范围的那些。但我的问题是,我根本不想因为性能问题而计算它们(大多数情况下,最大值和最小值之间的范围在 2 左右)。
此外,同样出于性能原因,我想避免所有相同的子集,因为它们使用被认为相等的两个版本的对象。
示例(使用整数而不是对象。您可以使用 bool AreSame(object1, object2) 检查它们是否相同:
Original set: {0, 1, 1, 5, 5, 6}
Minimum: 2
Maximum: 3
Expected result: {{0, 1}, {0, 5}, {0, 6}, {1, 1}, {1, 5}, {1, 6}, {5, 5}, {5, 6}, {0, 1, 1}, {0, 1, 5}, {0, 1, 6}, {0, 5, 5}, {0, 5, 6}, {1, 1, 5}, {1, 1, 6}, {1, 5, 5}, {1, 5, 6}, {5, 5, 6}}
Original set: {0, 1, 2}
Minimum: 1
Maximum: 4
Expected result: {{0}, {1}, {2}, {0, 1}, {0, 2}, {1, 2}, {0, 1, 2}}
编辑:目前,我有this answer中给出的代码的修改版本
public static List<List<Tile>> GetSubsets(List<Tile> set, int min, int max)
{
List<List<Tile>> result = new List<List<Tile>>();
int length = set.Count;
int max = (int)Math.Pow(2, set.Count);
for (int count = 0; count < max; count++)
{
List<Tile> subset = new List<Tile>();
uint rs = 0;
while (rs < length && subset.Count() <= max)
{
if ((count & (1u << (int)rs)) > 0)
{
subset.Add(list[(int)rs]);
}
rs++;
}
if (subset.Count() <= max && subset.Count() >= min && !isInSet(result, subset))
result.Add(subset);
}
return result;
}
isInSet 基本上是一个函数,使用其他相等的对象进行 linq 查询以了解子集是否已经存在。
从技术上讲,这是可行的。但在实践中,问题实际上与性能有关。我有很多相同的对象,因此这计算了太多的子集。然后,我还计算了大量最终丢弃的子集。我的问题是如何在代码中添加这两个概念,以实际加速它,当子集不符合我的需求时,避免尽可能多的操作。我不知道该怎么做。
【问题讨论】:
-
“我尝试过的任何一个都不能满足我的特定需求,即使我尝试调整它们” - 如前所述,您的问题太宽泛了。您要求 Stack Overflow 从头开始编写您的实现。请提供一个好的minimal reproducible example,以显示您的尝试最接近成功,关于调整 Stack Overflow 上已经存在的许多现有答案之一。详细解释您的特定场景如何无法通过该实现解决,以及您在具体方面遇到的问题。
-
我已经编辑了问题以添加我的有效尝试,因为问题在于让它更快。显然,由于我的需求的性质,如果我只想要大小为 10-12 的子集并且在原始集合中只有三种不同类型的对象,那么目前大量的操作都是徒劳的尺寸 30。
-
如果您使用
new HashSet<HashSet<Tile>>(HashSet<Tile>.CreateSetComparer());而不是new List<List<Tile>>();会起作用吗? (Tile可能要实现IComparable)
标签: c# algorithm set subset combinations