Получение всех возможных комбинаций из списка номеров
Я ищу эффективный способ добиться этого:
у вас есть список чисел 1.....n (обычно: 1..5 или 1..7 или около того - достаточно маленький, но может варьироваться от случая к случаю)
вам нужны все комбинации всех длин для этих чисел, например, все комбинации только одного числа ({1}, {2}, .... {n}), затем все комбинации двух разных чисел ({1,2}, {1,3}, {1,4} ..... {n-1, n}), затем все комбинации для трех из этих чисел ({1,2,3}, {1,2,4}) и так далее
По сути, в пределах группы порядок не имеет значения, поэтому {1,2,3} эквивалентно {1,3,2} - это просто вопрос получения всех групп из x чисел из этого списка
Похоже, для этого должен быть простой алгоритм, но я тщетно искал до сих пор. Кажется, что большинство комбинаторных и перестановочных алгоритмов а) принимают во внимание порядок (например, 123 не равен 132), и они всегда, кажется, работают с одной строкой символов или чисел....
У кого-нибудь есть отличный алгоритм nice'n'quick?
Спасибо!
3 ответа
Просто увеличьте двоичное число и возьмите элементы, соответствующие установленным битам.
Например, 00101101
означало бы взять элементы с индексами 0, 2, 3 и 5. Так как ваш список просто 1..n, элемент просто индекс + 1.
Это будет генерировать перестановки в порядке. Другими словами, только {1, 2, 3}
будет сгенерировано. Не {1, 3, 2}
или же {2, 1, 3}
или же {2, 3, 1}
, так далее.
Не мой код, но вы ищете powerset. Google дал мне это решение, которое, кажется, не работает:
public IEnumerable<IEnumerable<T>> GetPowerSet<T>(List<T> list)
{
return from m in Enumerable.Range(0, 1 << list.Count)
select
from i in Enumerable.Range(0, list.Count)
where (m & (1 << i)) != 0
select list[i];
}
Источник: http://rosettacode.org/wiki/Power_set
Это то, что я написал в прошлом, чтобы выполнить такую задачу.
List<T[]> CreateSubsets<T>(T[] originalArray)
{
List<T[]> subsets = new List<T[]>();
for (int i = 0; i < originalArray.Length; i++)
{
int subsetCount = subsets.Count;
subsets.Add(new T[] { originalArray[i] });
for (int j = 0; j < subsetCount; j++)
{
T[] newSubset = new T[subsets[j].Length + 1];
subsets[j].CopyTo(newSubset, 0);
newSubset[newSubset.Length - 1] = originalArray[i];
subsets.Add(newSubset);
}
}
return subsets;
}
Это универсальный тип, поэтому он будет работать для целых, длинных, строковых, Foos и т. Д.