繁体   English   中英

遍历数组的所有可能组合

[英]Loop Through Every Possible Combination of an Array

我通过在C#依赖于规模,而不是为了一个阵列的每个组合试图循环。 例如: var states = ["NJ", "AK", "NY"];

一些组合可能是:

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

依此类推...在我的情况下, states = ["NJ","NY"]states = ["NY","NJ"]也是同一件事,因为顺序无关紧要。

有没有人对最有效的方式任何想法做到这一点?

以下两种方法的组合应该可以实现您想要的。 这个想法是,如果项数为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)取得索引i中的项目,要么(2)不取得索引i中的项目。

此问题的伪代码:

主要代码:

  • 定义states长度的布尔数组(例如,命名为picked
  • 调用索引为0的回溯方法(第一项)

回溯功能:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM