Нахождение всех перестановок массива

194
20 ноября 2018, 16:30

Есть массив элементов, и необходимо вычислить все возможные варианты упорядочения массива.

Массив выглядит так

$arr = explode(' ', 'she sells seashells');

Хочу получить следующий результат

she sells seashells
sells she seashells
she seashells sells
seashells she sells
sells seashells she
seashells sells she

Я новичок в этом деле,так что буду рад любой помощи.Спасибо

Answer 1

Используйте один из двух алгоритмов перестановки, обсуждаемых далее.

Обсуждение

Функция pc_permute(), приведенная в примере 1 – это PHP модификация базовой рекурсивной функции.

примере 1

function pc_permute($items, $perms = array()) {
    if (empty($items)) {
        echo implode(' ', $perms) . "<br>";
    } else {
        for ($i = count($items) -1; $i >= 0; --$i) {
            $newitems = $items;
            $newperms = $perms;
            list($foo) = array_splice($newitems, $i, 1);
            array_unshift($newperms, $foo);
            pc_permute($newitems, $newperms);
        }
    }
}
pc_permute(explode(' ', 'she sells seashells'));

Эта рекурсия хотя и элегантна, но неэффективна, поскольку делает повсюду копии. К тому же не так легко модифицировать эту функцию, чтобы она возвращала значения вместо вывода на печать без накопле ния их в глобальной переменной.

примере 2

function pc_next_permutation($p, $size) {
    // проходим массив сверху вниз в поисках числа, которое меньше следующего
    for ($i = $size - 1; $p[$i] >= $p[$i+1]; --$i) { }
    // если такого нет, прекращаем перестановки
    // массив перевернут: (1, 2, 3, 4) => (4, 3, 2, 1)
    if ($i == -1) { return false; }
    // проходим массив сверху вниз в поисках числа,
    // превосходящего найденное ранее
    for ($j = $size; $p[$j] <= $p[$i]; --$j) { }
    // переставляем их
    $tmp = $p[$i]; $p[$i] = $p[$j]; $p[$j] = $tmp;
    // теперь переворачиваем массив путем перестановки элементов,
    // начиная с конца
    for (++$i, $j = $size; $i < $j; ++$i, --$j) {
        $tmp = $p[$i]; $p[$i] = $p[$j]; $p[$j] = $tmp;
    }
    return $p;
}
$set = explode(' ', 'she sells seashells');
$size = count($set) -1;
$perm = range(0, $size);
$j = 0;
do {
    foreach ($perm as $i) { $perms[$j][] = $set[$i]; }
} while ($perm = pc_next_permutation($perm, $size) and ++$j);
foreach ($perms as $p) {
    echo implode(' ', $p) . "<br>";
}

Идея Доминуса состоит в том, что вместо манипуляций с самим массивом можно создавать перестановки целых чисел. Затем, чтобы получить истинную перестановку, снова ставим в соответствие числам элементы массива – оригинальная мысль. Однако этот прием имеет некоторые недостатки. Для нас, программистов на PHP, более важными являются частые извлечения, вставки и объединения массивов, т. е. то, что для Perl является центральным. Затем процесс вычисления перестановок целых чисел проходит через серию шагов, которые выполняются для каждой перестановки; и поскольку он не запоминает предыдущие перестановки, то каждый раз начинает с исходной перестановки. Зачем работает повторное выполнение, если мы можем помочь ему?

READ ALSO
YouCompleteMe не работает с заголовочными файлами

YouCompleteMe не работает с заголовочными файлами

Недавно решил установить YouCompleteMe и обнаружил, что, несмотря на то, что все прекрастно работает сcpp файлами, тем не менее автодополнение не работает...

307
С++ : Ошибка C2039

С++ : Ошибка C2039

name не является членом std::vector<man,std::allocator<_Ty>>Вроде решения находил, но в моем случае не спасло

177
C++ - передача массива в функцию

C++ - передача массива в функцию

Есть несколько функций, которые принимают в качестве параметра массив целых чисел

229
c extern при множественном объявлении

c extern при множественном объявлении

Подскажите, как ведет себя extern в следующей ситуации:

190