/*
* 求一个字符串所有的排列组合,字符串可以有重复的字符,
*
*(注意如果字符串中间有数组的话是没有进行清除的)
*/
/*
* 思路:
* 1.检查字符串是否规范,检查字符串长度,如果为空或者只有一个字符,直接输出,
* 如果大于1初始化链表list并进行下面操作;
* 2.从第一个字符开始逐一从后面取一个字符
* 3.用一个缓存数组flag寄存前面的链表list,并清空链表list;
* 4.将取出的字符与前面的字符串所排列出的各种组合进行重新排列,
* 即用该字符与每一个缓存的flag键值进行排列;
* 5.每生成一个新的字符串要与前面的已经排列好的字符进行对比,如果有重复的,则放弃加入链表list
* 6.按照前面的步骤列出每一个不重复的字符串加入链表list,直到找出所有的排列
*/
class string_combinations {
private $string;
private $list;
public function __construct($string) { // 初始化
$this->string = trim ( $string );
$this->list = array ();
}
private function check_str() {
// 检查字符串
}
public function str_insert($string, $replace, $afternum) { // 将指定字符串插入指定的位置后面
$before = substr ( $string, 0, $afternum );
$after = substr ( $string, $afternum );
$newstr = $before . $replace . $after;
return $newstr;
}
public function str_combinations() {
$list = $this->list; // 字符串排列数组
$str = $this->string;
$str_len = strlen ( $str ); // 字符串长度
if ($str_len <= 1) { // 如果字符串长度为1,直接输出,并停止执行后面的代码
$this->list [] = $str;
return $this->list;
exit ();
}
$flag = array (); // 缓存数组
$list [] = substr ( $str, 0, 1 ); // 为$list设置初值
for($i = 1; $i < $str_len; $i ++) { // 如果字符串大于1,执行n-1次循环
$replace = substr ( $str, $i, 1 ); // 取出下一个要替换的字符
unset ( $flag ); // 清空上一次的缓存
$flag = $list; // 将上一次排列好的数组赋值给新的缓存
$list = array (); // 清空上一次排列好的内容,准备接收新内容,注意不能用unset()清空,因为后面还要将其作为数组使用,而如果清空了,当没有数据时,其就是个普通变量
$laststrlen = strlen ( $flag [0] ); // 上一次排列的字符串的长度
foreach ( $flag as $value ) {
for($k = $laststrlen; $k >= 0; $k --) { // 要替换的字符串的插入位置有$flag2str_len+1个,因此执行$flag2str_len次插入操作
$v = $this->str_insert ( $value, $replace, $k );
$res = array_search ( $v, $list ); // 检查数组中是否存在该值
if ($res === false) { // 如果不存在该值,则加入数组,如果存在不加入链表
$list [] = $v;
}
}
}
}
$this->list = $list;
return $this->list;
}
}
/* 测试 */
$str = '123';
$strcom = new string_combinations ( $str );
$list = $strcom->str_combinations ();
var_dump ( $list );
实现一个字符串的所有排列组合
最新推荐文章于 2021-04-01 22:10:33 发布