打印字符的所有排列

code

function test($arr, $str = ''){
	$len = count($arr);

    if($len == 1){
        echo $str . $arr[0] . PHP_EOL;
        return;
    }

    for ($i = 0; $i < count($arr); $i++) {
        $tmp = $arr[0];
        $arr[0] = $arr[$i];
        $arr[$i] = $tmp;

        test(array_slice($arr, 1), $str . $arr[0]);
    }
}

$string = 'abcdef';
test(str_split($string));

原理分析

首先不考虑递归,只说函数本身的这个for循环,它的作用是让每个元素都和第一个元素交换一次位置。

然后把数组第一个元素拿掉,进行递归,这样后面的元素也都是这个逻辑,让每个元素和第一个元素交换一次位置。

然后分析递归,简单点,假设字符串是abcd

那么随着递归的进行,参数传入分别是:
([a,b,c,d],’’) (首次调用函数)
([b,c,d],a) (第一层递归)
([c,d],ab) (第二层递归)
([d],abc) (第三层递归)
当数组元素为1个时,根据逻辑将会输出 abcd , 然后return,此时回到第二层递归的for循环中。
for循环再次执行后再次交换元素,此时$i的值为1,$arr[0]$arr[$i]进行元素交换后,$arr[0]的值为d,$arr[$i]的值为c。
然后再次进入第三层递归,此时的传参是: ([c],abd),然后第三层的递归根据逻辑会输出 abdc ,然后再return到第二层递归中。
当第二层递归循环完之后,第一次递归的for循环会继续执行,然后以此类推…

由此可见,每一层递归当中,都是负责将自己收到的数组的每个元素和第一个元素进行一次交换,然后传递下去,每一层递归都可以保证从自己这一层开始,后面的元素都能得到充分的交换,这也就达到了打印一个字符串所有排列方式的目的。
这种实现的缺点是,计算时所损耗的内存会随着字符串长度增加而增加。

发布了116 篇原创文章 · 获赞 12 · 访问量 99万+

猜你喜欢

转载自blog.csdn.net/u012628581/article/details/102907108