剑指 Offer 38. 字符串的排列
问题描述
输入一个字符串,打印出该字符串中字符的所有排列。
你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。
示例:
输入:s = "abc"
输出:["abc","acb","bac","bca","cab","cba"]限制:
1 <= s 的长度 <= 8
解题思路
这道题主要解题的思路就是怎样完成全排列的回溯代码,列举出所有排列。
其次还需要注意两点:
1是需要把最后结果输出为String,我是用List来存储的,因为会比较方便一些,最后输出前就需要转换为String[]数组。
2是为了解决重复字符串,不出现重复全排列的问题,使用used数组,来判重。具体原理见:Leecode#78. 子集+#90. 子集 II(回溯+解决重复元素不重复组合问题)
与上面的题目不一样的地方在于,使用used数组去重时,需要对数据进行排序,使相同的元素在一起。而这道题的输入是一个字符串,因此需要先转换为char[]数组,再对数组排序,再生成新的字符串。
需要注意,当我偷懒使用以下代码完成转换时会报错。需要注意。
s = new String(Arrays.sort(s.toCharArray()));
Java解法
class Solution {
List<String> res = new ArrayList<>();
String tmp="";
public String[] permutation(String s) {
char [] tmp = s.toCharArray();
Arrays.sort(tmp);
String news = new String(tmp);
boolean [] used = new boolean [s.length()];
backtracking(news,used);
String [] ss = new String [res.size()];
int ind=0;
for(String str:res){
ss[ind++]=str;
}
return ss;
}
public void backtracking(String s,boolean [] used){
if(tmp.length()==s.length()){
res.add(tmp);
return;
}
for(int i=0;i<s.length();i++){
if(i>0 && s.charAt(i-1)==s.charAt(i) && used[i-1]==false) continue;
if(used[i]==false){
tmp+=s.charAt(i);
used[i] = true;
backtracking(s,used);
tmp = tmp.substring(0,tmp.length()-1);
used[i] = false;
}
}
}
}