循环遍历数组的每个可能组合

时间:2015-04-07 16:44:56

标签: c# arrays

我试图在C#中依赖于大小而不是顺序遍历数组的每个组合。例如:var states = ["NJ", "AK", "NY"];

某些组合可能是:

states = [];
states = ["NJ"];
states = ["NJ","NY"];
states = ["NY"];
states = ["NJ", "NY", "AK"];

依旧...... 在我的情况下,states = ["NJ","NY"]states = ["NY","NJ"]是相同的,因为顺序并不重要。

有没有人对最有效的方法有任何想法?

2 个答案:

答案 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
  • 的bool数组(例如名为states
  • 使用索引0(第一项)
  • 调用回溯方法

回溯功能:

  • 接收states数组,其长度,当前索引和bool数组
  • 暂停条件 - 如果当前索引等于长度,则只需要遍历bool数组,对于每个正确的项目,打印来自states的匹配字符串
  • 实际回溯:
    • picked[i]设置为true并使用下一个索引调用回溯功能
    • picked[i]设置为false并使用下一个索引调用回溯功能