PHP实现字符串全排列的核心是递归或回溯,需处理重复字符去重,长字符串推荐SPL迭代器以节省内存,短字符串可用array_unique简化去重。

PHP 中实现字符串排列(即全排列)的核心是递归或回溯,目标是生成给定字符串所有字符的不重复排列组合。若字符串含重复字符,还需去重处理。
基础递归实现(无重复字符)
适用于字符互不相同的字符串,如 "abc"。思路是:每次固定一个字符在首位,对剩余字符递归求排列。
- 定义函数 permute($str),当长度为 1 时直接返回数组 [$str]
- 遍历字符串每个位置,取出当前字符 $char,拼接其余字符 $rest = substr($str,0,$i).substr($str,$i+1)
- 递归调用 permute($rest),将结果中每项前加上 $char
- 合并所有结果并返回
支持重复字符的去重版本
当输入如 "aab" 时,朴素递归会产生重复排列(如 "aab" 出现多次)。可在递归前对字符排序,并跳过相邻相同字符:
- 先将字符串转为字符数组:$chars = str_split($str),再 sort($chars)
- 递归中用 for 循环,若 $i > 0 && $chars[$i] === $chars[$i-1] 且未被使用,则跳过(需配合标记数组)
- 更简单方式:生成全部排列后用 array_unique() 去重(适合短字符串,效率低但易懂)
使用 SPL 迭代器(内存友好)
对长字符串,递归易爆栈或占大量内存。可用 PHP 的 Iterator 模式逐个生成排列:
立即学习“PHP免费学习笔记(深入)”;
- 实现自定义类 StringPermutationIterator,继承 Iterator
- 内部维护当前排列状态与下一个排列算法(如字典序下一个排列:先找最长非增后缀,再找后缀中首个大于前驱的字符,交换后翻转后缀)
- 调用时用 foreach 遍历,不一次性加载全部结果
一行简洁版(仅作演示,不推荐生产)
利用 eval 和 str_split 可写出极简但不可读、不安全的版本,例如:
array_reduce(str_split($s), function($a,$c) { return array_merge(...array_map(function($v) use($c) { return array_map(function($i) use($v,$c) { return substr($v,0,$i).$c.substr($v,$i); }, range(0, strlen($v))); }, $a)); }, ['']);
该写法嵌套深、难调试,仅体现函数式风格,实际项目应优先选清晰递归或迭代器方案。











