1. 问题描述:
求解出字符串"ABCDE"的全排列
2. 思路分析:
① 在之前的求解全排列的思路中我们使用到的是将当前位置与其他位置进行交换,比如求解1-9的全排列我们可以将第一个位置与上的数字与2-9位置上的数字进行交换,对于第二个位置的数字与3-9位置上的数字进行交换.... 所以可以对当前位置上的数字进行递归求解形成所有的全排列
② 除了上面求解数字的全排列,我们也可以求解出某个字符串的全排列,思路是将当前位置上的字符使用临时变量保存下来,然后截取除了这个字符剩下来的所有字符,对截取下来的字符串进行递归进行求解,当当前的递归结束那么把结果返回,并且将之前临时保存的那个字符与递归求解的结果相加拼接,所以递归求解的结果需要返回一个List<String>来进行保存
比如一开始的时候以A这个字符为首字母,末尾两次递归求解的简单过程如下:
A
B
C
D E
E D
为什么要使用List<String>来保存上一次的递归结果呢?从图中我们可以看出当递归到D这个位置,再一次递归调用形成DE,然后因为有一个循环所以需要执行平行状态递归到E这个位置,再一次递归调用形成ED,当这两次都调用完了分别将各自的List<String>结果返回给C这个位置调用的结果(并且每返回一次的List<String>长度都是1),把C这个字符与往下调用的结果进行拼接,所以这两次形成的结果是不一样的,我们需要在每一次递归的方法之前创建一个新的List<String>来保存结果,这样把每一次返回的不同结果都加入到List中
上面画的图还可以进一步进行扩展,分别画出平行状态那么就比较好理解了
3. 具体的代码如下:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> res = f("ABCDE");
for(int i = 0; i < res.size(); i++){
System.out.println(res.get(i));
}
}
public static List<String> f(String s){
List<String> list = new ArrayList<String>();
if(s.length() == 1){
list.add(s);
return list;
}
for(int i = 0; i < s.length(); i++){
char c = s.charAt(i);
List<String> t = f(s.substring(0, i) + s.substring(i + 1));
for(int j = 0; j < t.size(); j++){
list.add(c + t.get(j));
}
}
return list;
}
}