Сегодня я решил рассказать о решении задачи генерации перестановок различной длины из заданного массива.
Сама задача выглядит следующим образом: Дан массив чисел. Необходимо получить все уникальные комбинации данных чисел длины N. (комбинации [1, 2, 3], [2, 1, 3], [3, 2, 1] … — считается одной и той же). Так же необходимо предусмотреть возможность исключать из исходного массива определенные значения (или индексы). С первого взгляда данная задача кажется простой. Однако на практике при реализации данной задачи многие сталкиваются с трудностями.
Для такого чтобы решить данную задачу нам необходимо использовать рекурсию. Общая логика решения задачи такая: проходим по исходному массиву слева направо. Если текущий индекс (или значение) попадает под фильтр — переходим к следующему элементу, в противном случае добавляем значение в результат «A». Как только в результате «A» становиться число элементов равное N нам необходимо сохранить полученный массив в массив «B», и откатиться в массиве «A» на шаг до добавления последнего элемента (по сути удалить последнее добавление, которое привело к числу элементов N).
Реализация:
//array - исходный массив //skip - индексы, которые нужно пропустить //current - служебный параметр (индекс с которого начинаем работу в массиве array - передаем значение 0 при первом вызове) //max - число элементов в перестановке //result - переменная для сохранения результата private void Сombinations(int[] array, Listskip, int current, int max, List > result) { if (result.Count == 0) //частный случай { result.Add(new List
()); } if (max == 0) //частный случай { return; } var currentLevelResult = new List (result.Last()); //сохраняем текущее состояние (до добавления нового элемента) for (int i = current; i < array.Length; ++i) { if (skip.Contains(i)) //если пропускаем значения skip.Contains(array[i]) { continue; } result.Last().Add(array[i]); if (result.Last().Count != max) { Сombinations(array, skip, i + 1, max, result); } result.Add(new List (currentLevelResult)); } if (result.Last().Count != max) //Если исходный массив закончился и в результате недостаточно элементов - удаляем такой результат { result.Remove(result.Last()); } }
Пример использования:
List> result = new List
>(); Сombinations(new int[] {1, 2, 3}, new List
(), 0, 2, result); /* result [0] = [1,2] [1] = [1,3] [2] = [2,3] */