这不应该太难,但是我的想法似乎是堆栈溢出(色相)。我有一系列的列表,我想找到它们可以排序的所有排列。所有列表的长度都不同。
例如:
清单1:1
清单2、1、2
所有排列将是:
1、1
一二
就我而言,我不会切换数字。(例如2、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嵌套循环(,其中N是input.Count),如下所示(在伪代码中):
GenerateCombinations
N
input.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; } } }