PHP 递归经典算法实例
排列算法
首先明确函数的输入和输出,输入是一个字符串还有排列的个数,输出用数组来表示,所以函数的雏形应该是这样的
function permutation($str, $len)
{
$res = [];
if ($len == 1) {
$res = str_split($str);
} else {
//todo
}
return $res;
}
接着进行第二步,假设我们已经知道了len-1的输出,要由这个输出得出len的输出。在这个问题里,如果我已经知道了“abcd”选取2个的输出的集合,现在要“abcd”的选取3个集合,要怎样得出呢?
不难发现“abcd”选取1个的结果(a,b,c,d),与“abcd”选取2个的结果(ab,ac,ad,ba,bc,bd,…)的关系,在(a,b,c,d)后面循环插入单个元素与“abcd”的差集。于是得到如下算法。
function permutation($str, $len)
{
$res = [];
if ($len == 1) {
$res = str_split($str);
} else {
$list = permutation($str, $len - 1);
foreach ($list as $vo) {
$_arr = array_diff(str_split($str), str_split($vo));
foreach ($_arr as $item) {
$res[] = $vo . $item;
}
}
}
return $res;
}
//测试结果
echo PHP_EOL . '<==排列==>' . PHP_EOL;
$res = permutation('abcd', 2);
print_r($res);
组合算法
组合与排列类似,在插入元素时索引必须大于原来集合的任意一个元素的索引
function combination($str, $len)
{
$res = [];
if ($len == 1) {
$res = str_split($str);
} else {
$list = combination($str, $len - 1);
foreach ($list as $vo) {
$_arr = array_diff(str_split($str), str_split($vo));
$index1 = strpos($str, substr($vo, -1, 1));
foreach ($_arr as $item) {
$index2 = strpos($str, $item);
//在插入元素$item时索引必须大于原来集合的任意一个元素的索引
if ($index2 > $index1) $res[] = $vo . $item;
}
}
}
return $res;
}
echo PHP_EOL . '<==组合==>' . PHP_EOL;
$res = combination