【问题标题】:Php recursion to get all possibilities of stringsphp递归获取字符串的所有可能性
【发布时间】:2011-05-15 20:23:10
【问题描述】:

这是我获得所有可能性的代码:

$seq[1] = 'd';
$seq[2] = 'f';
$seq[3] = 'w';
$seq[4] = 's';

for($i = 1; $i < 5; $i++)
{
    $s['length_1'][] = $seq[$i];
    $c1++;

    for($i2 = $i+1; $i2 < 5; $i2++)
    {
        $s['length_2'][] = $seq[$i].$seq[$i2]; 
        $last = $seq[$i].$seq[$i2]; 
        $c2++;

        for($i3 = $i2+1; $i3 < 5; $i3++)
        { 
            $s['length_3'][] = $last.$seq[$i3];
            $last = $last.$seq[$i3];    
            $c3++;

            for($i4 = $i3+1; $i4 < 5; $i4++)
            {
                $s['length_4'][] = $last.$seq[$i4];   
                $c4++;  
            }
        }
    }
}

for($i = 0; $i < $c1; $i++)
    echo $s['length_1'][$i].'<br>'; 

for($i = 0; $i < $c2; $i++)
    echo $s['length_2'][$i].'<br>';   

for($i = 0; $i < $c3; $i++)
    echo $s['length_3'][$i].'<br>';  

for($i = 0; $i < $c4; $i++)
    echo $s['length_4'][$i].'<br>';    

但如果我想添加更多,那么我将不得不再添加一个循环。那么,我该如何使用递归呢?我努力,我努力,但我真的做不到。 请帮助并尽可能简单地发布示例。

谢谢。

【问题讨论】:

标签: php recursion


【解决方案1】:

这里有一个算法,

function getCombinations($base,$n){

$baselen = count($base);
if($baselen == 0){
    return;
}
    if($n == 1){
        $return = array();
        foreach($base as $b){
            $return[] = array($b);
        }
        return $return;
    }else{
        //get one level lower combinations
        $oneLevelLower = getCombinations($base,$n-1);

        //for every one level lower combinations add one element to them that the last element of a combination is preceeded by the element which follows it in base array if there is none, does not add
        $newCombs = array();

        foreach($oneLevelLower as $oll){

            $lastEl = $oll[$n-2];
            $found = false;
            foreach($base as  $key => $b){
                if($b == $lastEl){
                    $found = true;
                    continue;
                    //last element found

                }
                if($found == true){
                        //add to combinations with last element
                        if($key < $baselen){

                            $tmp = $oll;
                            $newCombination = array_slice($tmp,0);
                            $newCombination[]=$b;
                            $newCombs[] = array_slice($newCombination,0);
                        }

                }
            }

        }

    }

    return $newCombs;


}

我知道它无论如何都不是有效的,但是在小集合中使用应该不是问题

第一个基本参数是一个数组,其中包含生成组合时要考虑的元素。

简单的使用和输出:

var_dump(getCombinations(array("a","b","c","d"),2));

输出是

array
  0 => 
    array
      0 => string 'a' (length=1)
      1 => string 'b' (length=1)
  1 => 
    array
      0 => string 'a' (length=1)
      1 => string 'c' (length=1)
  2 => 
    array
      0 => string 'a' (length=1)
      1 => string 'd' (length=1)
  3 => 
    array
      0 => string 'b' (length=1)
      1 => string 'c' (length=1)
  4 => 
    array
      0 => string 'b' (length=1)
      1 => string 'd' (length=1)
  5 => 
    array
      0 => string 'c' (length=1)
      1 => string 'd' (length=1)

要列出数组的所有子集,使用这种组合算法只需执行

$base =array("a","b","c","d");

for($i = 1; $i<=4 ;$i++){
    $comb = getCombinations($base,$i);

    foreach($comb as $c){
        echo implode(",",$c)."<br />";
    }

}

输出是

a
b
c
d
a,b
a,c
a,d
b,c
b,d
c,d
a,b,c
a,b,d
a,c,d
b,c,d
a,b,c,d

【讨论】:

  • 在像 Array 这样的列表中 ( [0] => 10 [1] => 10 [2] => 14 [3] => 39 [4] => 39 [5] => 39 [6] => 39 [7] => 40 [8] => 40 [9] => 42 [10] => 42 [11] => 45 ) 我怎样才能创建像 10、10、14 这样的排列而不是只有10、14、39?
【解决方案2】:

这是一个简单的算法。从 1 迭代到 2count(array)-1。在每次迭代中,如果循环计数器的二进制表示中的第 j 位等于 1,则在组合中包含第 j 个元素。

由于 PHP 需要能够将 2count(array) 计算为整数,因此这可能永远不会超过 PHP_INT_MAX。在 64 位 PHP 安装中,您的数组不能超过 62 个元素,因为 262 低于 PHP_INT_MAX 而 263 超过它。

编辑:这会计算所有可能的组合,而不是排列(即,'abc' = 'cba')。它通过以二进制表示原始数组并从 0 到整个数组的二进制表示“向上计数”来实现这一点,从而有效地构建了每个可能的唯一组合的列表。

$a = array('a', 'b', 'c', 'd');

$len  = count($a);
$list = array();

for($i = 1; $i < (1 << $len); $i++) {
    $c = '';
    for($j = 0; $j < $len; $j++)
        if($i & (1 << $j))
            $c .= $a[$j];
    $list[] = $c;
}

print_r($list);

【讨论】:

  • 这不会测试所有的可能性.. 例如,如果只选择 [a, b] 它会输出:a b ab what about "ba"?
  • “ba”在组合或集合方面与“ab”相同。您要寻找的是排列。
  • 当我将您的代码与$a = range('A', 'Z'); 一起使用时出现内存错误,下面@KemalDağ 的代码工作正常。
【解决方案3】:

这里是:

<?php
function combinations($text,$space)
{
    // $text is a variable which will contain all the characters/words of which  we want to make all the possible combinations
    // Let's make an array which will contain all the characters
    $characters=explode(",", $text);
    $x=count($characters);

    $comb = fact($x);

    // In this loop we will be creating all the possible combinations of the  positions that are there in the array $characters

    for ($y=1; $y<= $comb; $y++)
    {
        $ken = $y-1;
        $f = 1;
        $a = array();
        for($iaz=1; $iaz<=$x; $iaz++)
            {
                $a[$iaz] = $iaz;
                $f = $f*$iaz;
            }
        for($iaz=1; $iaz<=$x-1; $iaz++)
            {
                $f = $f/($x+1-$iaz);
                $selnum = $iaz+$ken/$f;
                $temp = $a[$selnum];
                for($jin=$selnum; $jin>=$iaz+1; $jin--)
                    {
                        $a[$jin] = $a[$jin-1];
                    }
                $a[$iaz] = $temp;
                $ken = $ken%$f;
            }
        $t=1;

           // Let’s start creating a word combination: we have all the  necessary positions
        $newtext="";

        // Here is the while loop that creates the word combination
        while ($t<=$x)
            {
                $newtext.=$characters[$a[$t]-1]."$space";
                $t++;
            }
        $combinations[] =  $newtext ;
    }

        return $combinations;

}

function fact($a){
if ($a==0) return 1;
else return $fact = $a * fact($a-1);
}

$a = combinations("d,f,w,s","");
    foreach ($a as $v) {
            echo "$v"."\n";
    }

?>

输出:

dfws
dfsw
dwfs
dwsf
dsfw
dswf
fdws
fdsw
fwds
fwsd
fsdw
fswd
wdfs
wdsf
wfds
wfsd
wsdf
wsfd
sdfw
sdwf
sfdw
sfwd
swdf
swfd

另外,read this;

【讨论】:

  • 使用大量内存:/“PHP 致命错误:允许的内存大小为 134217728 字节已用尽(尝试分配 72 字节)...”
【解决方案4】:

你可以这样做:

function combinations($arr) {
    $combinations = array_fill(0, count($arr)+1, array());
    $combinations[0] = array('');
    for ($i = 0, $n = count($arr); $i < $n; ++$i) {
        for ($l = $n-$i; $l > 0; --$l) {
            $combinations[$l][] = implode('', array_slice($arr, $i, $l));
        }
    }
    return $combinations;
}

这是一个例子:

$arr = array('d', 'f', 'w', 's');
var_dump(combinations($arr));

这会产生以下数组:

array(
    array(''),                 // length=0
    array('d', 'f', 'w', 's'), // length=1
    array('df', 'fw', 'ws'),   // length=2
    array('dfw', 'fws'),       // length=3
    array('dfws')              // length=4
)

简要说明:

对于每一个i,0≤in,得到所有子数组arr‍[i,‍i+‍l] 每个可能的长度为 0 l ≤ n em> - 我。

【讨论】:

    【解决方案5】:

    这是我打印所有可能的字符组合的函数:

    function printCombinations($var, $begin = 0, $preText = "") {
        for($i = $begin; $i < count($var); $i++) {
            echo $preText . $var[$i] . "\n";
            if(($i+1) < count($var))
                printCombinations($var, $i+1, $preText . $var[$i]);
        }
    }
    
    printCombinations(array('a','b','c','d','e'));
    

    【讨论】:

      猜你喜欢
      • 2023-03-16
      • 2021-06-07
      • 2018-04-21
      • 2018-02-25
      • 1970-01-01
      • 2016-04-06
      • 1970-01-01
      • 2016-03-20
      相关资源
      最近更新 更多