这个递归代码如何找到字符串的所有排列?

时间:2013-10-15 14:13:54

标签: php algorithm recursion permutation

我正在做Project Euler个问题。我目前正在研究循环素数问题

  

这个数字197被称为循环素数,因为数字的所有旋转:197,971和719本身都是素数。

     

在100:2,3,5,7,11,13,17,31,37,71,73,79和97之下有十三个这样的素数。

     

在一百万以下有多少个圆形素数?

虽然检查某些东西是否是素数对我来说很容易,但我无法弄清楚如何得到数字的所有排列。经过大量搜索算法的提示后,我遇到了一个网站,它在Java中提供了代码,我在下面适用于PHP。但是,在继续解决问题之前,我真的想了解代码的不同部分究竟在做什么,特别是在for循环中。到目前为止我对它的理解是,在for循环中,它以空前缀开始,然后循环遍历字符串并将字符串中的单个元素添加到前缀,直到原始字符串中只剩下一个元素在这一点上,它回应了它。我理解正确吗?如果没有,我错过了什么?

<?php
    getallcombos("","1234");
    function getallcombos($prefix,$string){
        if(strlen($string)==1){
            echo $prefix.$string."<br>";
        }
        $array=str_split($string);
        for($i=0;$i<strlen($string);$i++){
            $newstr=substr($string,0,$i).substr($string,$i+1);
            getallcombos($prefix.$array[$i],$newstr);
        }                       
    }       
?>

2 个答案:

答案 0 :(得分:3)

问题不是要求排列,而是要求轮换。这是不同的。对于所有轮换,您可以循环:

var number = "2031";
var rotations = [];
for (i = 0; i < number.length; ++i) {
    number = number.substring(1)
           + number[0];
    rotations.push(number);
}
console.log(rotations);

http://jsfiddle.net/T6Mur/

更新

特别适合您:

function allRotArePrime(number) {
    var int;
    for (i = 0; i < number.length; ++i) {
        int = parseInt(
            number.substring(i) +
            number.substring(0, i)
        );
        // if (!isPrime(int)) return false;
        console.log(int);
    }
    //return true;
}

var num = 1927;
allRotArePrime(num.toString());

http://jsfiddle.net/T6Mur/3/

答案 1 :(得分:0)

if是你的停止条件。如果string仅为长度1,则只有一个排列。

for循环很复杂但它的确如下:

"" "1234" - &gt;循环4次,给出:

"1", "234"
"2", "134"
"3", "124"
"4", "123"

基本上它将一个字符从string移动到prefix,并且它会执行所有组合以获得所有排列。

然后它运行然后下一个循环,它给出:

"12" "34"
"13" "24"
"14" "23"
"21" "34"
.. etc

最终你会得到:

"123" "4" -> "1234"
"124" "3" -> "1243"
.. etc

关于你的问题:请注意,对于像777这样的数字来说效率会很低,只会给你777 6次。此外,您需要轮换,而不是排列。 197应该197,971,719而不是179,791,917