简体   繁体   中英

Algorithm for permutations

I am looking for an efficient combinations function that would take into account the order of the array. For example I want to generate all of the combinations of "hello world" but I don't want any of it reversed "world hello". I currently have a combinations function but it's too much.

Simple example :

$text = "Hello World"
$arr = explode(" ",$text); // string to array

And gives:

$result = combo_function($arr);
var_dump($result);

"Hello World"
"Hello" 
"World"

I do NOT want the inverse:

"World Hello"
  • the key is that I want it to be faster than combinations if possible.

Currently I am using this:

 // careful, this is very labor intensive ( O(n^k) )

public function buildSearchCombinations(&$set, &$results)
{
    for ($i = 0; $i < count($set); $i++) {

        $results[] = (string) $set[$i];
        $tempset = $set;
        array_splice($tempset, $i, 1);
        $tempresults = array();
        $this->buildSearchCombinations($tempset, $tempresults);

        foreach ($tempresults as $res) {
            $results[] = trim((string) $set[$i]) . " " . (string) trim($res);
        }
    }
}

I have a rather odd solution to this:

<?php

function supersetmember($set, $index) {
    $keys = array_reverse(str_split(decbin($index)));
    $member = [];
    foreach ($keys as $k => $v) {
        if ($v == 1) { 
            $member[] = $set[$k];
        }

    }
    return $member;
}


$text = "Hello World";
$arr = explode(" ",$text);
$total = pow(2,count($arr)); //Total permutations on size of set n is 2^n 
$superset = [];
for ($i = 0;$i < $total;$i++) {
    $superset[] = supersetmember($arr,$i);
}
print_r($superset);

Explanation:

There's 2^n sets that constitute a set of size n (including the empty set). You can map each of those sets as a natural number from 0 to (n-1). If you convert that number to binary then the digits that are 1 will indicate which members of the original set your subset will contain. Example:

Set = (A,B);

Superset member 2(decimal) = 10 (binary) which means the subset will include the second but not first member (we read the number from right to left as in from least significant to most significant digit).

The advantage of doing this is that you have a sort of a "fausset" algorithm (function supersetmember) which you give it a set and the subset you want and you get that subset.

The complexity of getting a single subset in the current version is O(n) but if you implement it with bit shifting you can reduce it to O(log n) In total the algorithm will be O(2^n) which is unavoidable because there are O(2^n) subsets to be generated.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM