1. 题目描述
输入一个字符串,打印出该字符串中字符的所有排列。
你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。
示例:
输入:s = “abc”
输出:[“abc”,“acb”,“bac”,“bca”,“cab”,“cba”]
限制:
1 <= s 的长度 <= 8
2. 题解
本题和 leetcode 47题 - 重复数字的全排列 相似,用回溯算法,难点在于如何处理 重复数字/字母。
1、我的提交
使用回溯算法,既然字母有重复的,我的想法是对字符串的下标进行全排列,通过set 过滤重复的字符串。
class Solution {
Set<String> res = new HashSet<>();
public String[] permutation(String s) {
if(s == null || s.length() == 0){
return new String[]{""};
}
helper(s, new ArrayList<Integer>());
//set转数组
return res.toArray(new String[res.size()]);
}
private void helper(String s, List<Integer> index){
if(index.size() == s.length()){
//下标数组转字符串
res.add(indexToString(s, index));
return;
}
// 遍历选择列表
for(int i = 0; i < s.length(); i++){
if(index.contains(i)){
continue;
}
// 做出选择
index.add(i);
// 进入下一步决策
helper(s, index);
// 撤回选择
index.remove(index.size()-1);
}
}
// 下标数组转字符串
private String indexToString(String s, List<Integer> index){
StringBuilder sb= new StringBuilder();
for(int i = 0; i < s.length(); i++){
sb.append(s.charAt(index.get(i)));
}
return sb.toString();
}
}
执行结果:
执行用时:155 ms, 在所有 Java 提交中击败了5.02%的用户
内存消耗:43.9 MB, 在所有 Java 提交中击败了20.15%的用户。
2、方法优化
class Solution {
public String[] permutation(String s) {
//使用list存储结果
List<String> res = new ArrayList<>();
//转换成char数组,并排序泛方便去重
char[] charArr = s.toCharArray();
Arrays.sort(charArr);
//回溯
backtrack(res, charArr, new StringBuilder());
//list转数组
return res.toArray(new String[res.size()]);
}
public void backtrack(List<String> res, char[] charArr, StringBuilder sb){
if(sb.length() == charArr.length){
res.add(sb.toString());
return;
}
for(int i = 0; i < charArr.length; i++){
//排除已经选择的字符
if(charArr[i] == '\0'){
continue;
}
//去重
if(i > 0 && charArr[i-1] != '\0' && charArr[i] == charArr[i-1]){
continue;
}
//做出选择
sb.append(charArr[i]);
char temp = charArr[i]; //保存
charArr[i] = '\0'; //做出标记
//进入下一步决策
backtrack(res, charArr, sb);
//撤回选择
sb.deleteCharAt(sb.length()-1);
charArr[i] = temp;
}
}
}
执行用时:9 ms, 在所有 Java 提交中击败了91.26%的用户
内存消耗:42.8 MB, 在所有 Java 提交中击败了74.90%的用户。
关键是去重的那一步,这个有待理解。
3. 一些技巧
先排序再去判断是否和前一个值重复;在原数组将值置为一个不会取到的值来进行标记;