我试图在C#中依赖于大小而不是顺序遍历数组的每个组合。例如:var states = ["NJ", "AK", "NY"];
某些组合可能是:
states = [];
states = ["NJ"];
states = ["NJ","NY"];
states = ["NY"];
states = ["NJ", "NY", "AK"];
依旧......
在我的情况下,states = ["NJ","NY"]
和states = ["NY","NJ"]
是相同的,因为顺序并不重要。
有没有人对最有效的方法有任何想法?
答案 0 :(得分:5)
以下两种方法的组合应该做你想要的。想法是如果项目的数量是n,那么子集的数量是2 ^ n。如果你从0迭代到2 ^ n - 1并查看二进制数字,你会得到每个项目的一个数字,如果数字是1那么你包括项目,如果它是0你没有。我在这里使用BigInteger
因为int
仅适用于少于32件商品的集合,而long
仅适用于少于64件商品。
public static IEnumerable<IEnumerable<T>> PowerSets<T>(this IList<T> set)
{
var totalSets = BigInteger.Pow(2, set.Count);
for (BigInteger i = 0; i < totalSets; i++)
{
yield return set.SubSet(i);
}
}
public static IEnumerable<T> SubSet<T>(this IList<T> set, BigInteger n)
{
for (int i = 0; i < set.Count && n > 0; i++)
{
if ((n & 1) == 1)
{
yield return set[i];
}
n = n >> 1;
}
}
使用以下代码
var states = new[] { "NJ", "AK", "NY" };
foreach (var subset in states.PowerSets())
{
Console.WriteLine("[" + string.Join(",", subset.Select(s => "'" + s + "'")) + "]");
}
会给你这个输出。
[]
['NJ']
['AK']
['NJ','AK']
['NY']
['NJ','NY']
['AK','NY']
['NJ','AK','NY']
答案 1 :(得分:1)
您可以在每次迭代中使用反向跟踪,您可以(1)获取索引i中的项目或(2)不接受索引i中的项目。
此问题的伪代码:
主要代码:
picked
states
)
回溯功能:
states
数组,其长度,当前索引和bool数组states
的匹配字符串picked[i]
设置为true
并使用下一个索引调用回溯功能picked[i]
设置为false
并使用下一个索引调用回溯功能