我的意思是,如果我有一套像
那样的话{ 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
可以#include <stdio.h>
int main ( void ) {
char A [ 2 ];
printf ( "Do you like this theme? Answer Y or N: " );
scanf ( "%d", A );
if ( A == "Y" ) {
printf ( "Good.\n" );
} else {
printf ( "Why not?\n" );
}
return 0;
}
任意数量的结果(甚至是无限量),是否有可能为子集问题编写解决方案?
答案 0 :(得分:0)
你在问题中指出了自己的缺陷。我们IEnumerable
不会在归档时终止。
事实上,如果你仔细编写你的set枚举器,它仍然可以返回另一个IEnumerable
。如果消息来源没有,那么这不会终止,但这并不是问题的全部。无论如何,十亿行的所有子集都会运行得太长,因此您可能永远不会遇到OutOfMemoryException
。
public static IEnumerable<IReadOnlyList<T>> AllSubcollections<T>(this IEnumerable<T> source)
{
// The empty set is always a subcollection
yield return new List<T>() { };
List<T> priors = new List<T>();
List<bool> includes = new List<bool>(); // Need a bitvector to get past 64 elements.
while (source.MoveNext())
{
for (int i = 0; i < includes.Count; ++i)
includes[i] = false;
// Always return the newest item in any set. This avoids dupes.
priors.Add(source.Current);
priors.Add(true);
bool breakout;
do {
List<T> set = new List<T>();
for (int i = 0; i < priors.Count; ++i)
if (includes[i])
set[i] = includes[i];
yield return (IReadOnlyList<T>)set;
// Bitvector increment
breakout = true;
for (int i = 0; i < priors.Count; ++i) {
if (!includes[i]) {
for (int j = 0; j < i; ++j)
includes[j] = 0;
includes[i] = true;
breakout = false;
break;
}
}
} while (!breakout);
}
}