Вы можете использовать любой алгоритм (например, известный Narayana algorithm) для генерации всех перестановок размера N
.
Теперь, если в этой общей последовательности перестановок вы считаете только перестановок с префиксом (а , A ..., а к), где < < ... < a k, то хвостовые части всех таких перестановок образуют последовательность всех возможных перестановок длины N - k
.
Таким образом, делая один проход через все перестановки длины N
, вы можете сгенерировать все перестановки длины N
и короче.
Вот что реализация С ++ может выглядеть
#include <iostream>
#include <algorithm>
#include <iterator>
int main()
{
int a[] = { 2, 3, 4, 5, 7, 8 };
do
{
for (auto ite = std::begin(a); ite != std::end(a); ++ite)
if (std::is_sorted(std::begin(a), ite))
{
std::copy(ite, std::end(a), std::ostream_iterator<int>(std::cout));
std::cout << std::endl;
}
} while (std::next_permutation(std::begin(a), std::end(a)));
}
(я взял на себя смелость предварительной сортировки ваш входной набор.)
выше, очевидно, не является оптимальным, так как последовательных вызовах std::is_sorted
внутри цикл for
будет повторно повторять/проверять, что уже было проверено на предыдущей итерации. Но опять же эта реализация предназначена только для иллюстративных целей.
Теперь возникает вопрос, довольны ли вы порядком, в котором эти перестановки сгенерированы. Приведенный выше подход не группирует их по длине.
В качестве альтернативы, вы можете перебирать all possible combinations, а затем просто генерировать все возможные перестановки для каждой комбинации.
@Ian Mercer: Неточный дубликат. Все возможные комбинации! = Все возможные перестановки. – AnT