题目
输入一个长度为 n 字符串,打印出该字符串中字符的所有排列,你可以以任意顺序返回这个字符串数组。
例如输入字符串ABC,则输出由字符A,B,C所能排列出来的所有字符串ABC,ACB,BAC,BCA,CBA和CAB。
数据范围:n<10
要求:空间复杂度O(n!),时间复杂度 O(n!)
输入描述:
输入一个字符串,长度不超过10,字符只包括大小写字母。
示例1
输入:"ab"
返回值:["ab","ba"]
说明:返回["ba","ab"]也是正确的
示例2
输入:"aab"
返回值:["aab","aba","baa"]
示例3
输入:"abc"
返回值:["abc","acb","bac","bca","cab","cba"]
示例4
输入:""
返回值:[""]
解答
源代码
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param str string字符串
* @return string字符串ArrayList
*/
public ArrayList<String> Permutation (String str) {
// write code here
ArrayList<String> res = new ArrayList<String>();
if (str == null) {
return res;
}
char[] charStr = str.toCharArray();
Arrays.sort(charStr);
boolean[] vis = new boolean[str.length()];
StringBuffer temp = new StringBuffer();
recursion(res, charStr, temp, vis);
return res;
}
public void recursion(ArrayList<String> res, char[] str, StringBuffer temp, boolean[] vis) {
if (temp.length() == str.length) {
res.add(temp.toString());
return;
}
for (int i = 0; i < str.length; i++) {
// 这个字符串已经访问过
if (vis[i]) {
continue;
}
if (i > 0 && str[i - 1] == str[i] && vis[i - 1]) {
continue;
}
temp.append(str[i]);
vis[i] = true;
recursion(res, str, temp, vis);
temp.deleteCharAt(temp.length() - 1);
vis[i] = false;
}
}
}
总结
递归+回溯。
将字符串转化为字符数组,进行递归回溯,递归过程中需要维护一个数组 vis 来记录各个字符是否被遍历过,用 temp 记录当前的组合序列。当 temp 的长度与所给的字符串长度相同时,就可以将 temp 加入结果 res 中了。