【发布时间】:2017-09-28 12:48:21
【问题描述】:
我的意思是,如果我有一套像
{ 1, 2, 3 }
那么所有子集都是
{ },
{ 1 },
{ 2 },
{ 3 },
{ 1, 2 },
{ 2, 3 },
{ 1, 3 },
{ 1, 2, 3 }
这是其中的2^3,因为集合的大小为3。我想到的任何解决方案都需要“记住”以前的子集,最大大小为n - 1,其中n 是集合的长度。例如,我有一个我写的解决方案,看起来像
public static IEnumerable<IEnumerable<T>> AllSubcollections<T>(this IEnumerable<T> source)
{
// The empty set is always a subcollection
yield return new List<T>() { };
T[] arr = source.ToArray();
IEnumerable<int> indices = Enumerable.Range(0, arr.Length);
var last = new List<HashSet<int>>(new List<HashSet<int>>() { new HashSet<int>() });
for(int k = 1; k < arr.Length; ++k)
{
var next = new List<HashSet<int>>(new List<HashSet<int>>());
foreach(HashSet<int> hs in last)
{
foreach(int index in indices)
{
if(!hs.Contains(index))
{
var addition = hs.Concat(new List<int> { index });
yield return addition.Select(i => arr[i]);
next.Add(new HashSet<int>(addition));
}
}
}
}
}
注意这是如何假设 source 可以放入数组中,并假设 HashSet 可以保存以前的子集合。
鉴于IEnumerable<T> 可以yield 获得任意数量的结果(甚至无限数量),是否可以编写一个解决方案来解决子集问题?
【问题讨论】:
-
@C.McCoyIV:他的解决方案在其输入上调用 .ToArray() 并想知道是否有可能为此编写一个不会在无限馈送时立即爆炸的算法。
标签: c# .net algorithm memory-management