一尘不染

如何迭代具有不同长度的列表以找到所有排列?

algorithm

这不应该太难,但是我的想法似乎是堆栈溢出(色相)。我有一系列的列表,我想找到它们可以排序的所有排列。所有列表的长度都不同。

例如:

清单1:1

清单2、1、2

所有排列将是:

1、1

一二

就我而言,我不会切换数字。(例如2、1)最简单的写法是什么?


阅读 240

收藏
2020-07-28

共1个答案

一尘不染

我不能说以下是否是最简单的方法,但是IMO是最有效的方法。这基本上是我对锯齿状阵列中的每种组合的回答的概括版本:

public static class Algorithms
{
    public static IEnumerable<T[]> GenerateCombinations<T>(this IReadOnlyList<IReadOnlyList<T>> input)
    {
        var result = new T[input.Count];
        var indices = new int[input.Count];
        for (int pos = 0, index = 0; ;)
        {
            for (; pos < result.Length; pos++, index = 0)
            {
                indices[pos] = index;
                result[pos] = input[pos][index];
            }
            yield return result;
            do
            {
                if (pos == 0) yield break;
                index = indices[--pos] + 1;
            }
            while (index >= input[pos].Count);
        }
    }
}

您可以在链接的答案中看到解释(很快它就是在模拟嵌套循环)。同样,由于出于性能方面的考虑,它会生成内部缓冲区而无需克隆它,因此如果要存储结果以供以后处理,则需要对其进行克隆。

用法示例:

var list1 = new List<int> { 1 };
var list2 = new List<int> { 1, 2 };
var lists = new[] { list1, list2 };

// Non caching usage
foreach (var combination in lists.GenerateCombinations())
{
    // do something with the combination
}

// Caching usage
var combinations = lists.GenerateCombinations().Select(c => c.ToList()).ToList();

更新:GenerateCombinations是一个标准的C#迭代器方法,该实现基本上模拟了N嵌套循环(,其中Ninput.Count),如下所示(在伪代码中):

对(INT I 0 = 0;我0 <输入[0] .Count之间;我0
对(INT I 1 = 0;我1 <输入[1] .Count之间;我1

对(INT I 2 = 0; i 2 <input [2] .Count; i 2

for(int i N-1 = 0; i N-1 <input [N-1] .Count; i N-1

yield {输入[0] [i 0 ],输入[1] [i 1 ],输入[2] [i 2 ],…,输入[N-1] [i N-1 ]}

或以其他方式显示:

for (indices[0] = 0; indices[0] < input[0].Count; indices[0]++)
{
    result[0] = input[0][indices[0]];
    for (indices[1] = 0; indices[1] < input[1].Count; indices[1]++)
    {
        result[1] = input[1][indices[1]];
        // ...
        for (indices[N-1] = 0; indices[N-1] < input[N-1].Count; indices[N-1]++)
        {
            result[N-1] = input[N-1][indices[N-1]];
            yield return result;
        }
    }
}
2020-07-28