题目描述
牛客网NC121字符串的排列:题目地址
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则按字典序打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
输入:
输入一个字符串,长度不超过9,可能有重复,值包含大小写字母
返回:
输出所有字符串列表
题目分析
参考官方思路,采用递归回溯法。
- 字典序通俗理解就是从首字母开始按从a~z排列,若首字母相同则按第二字母排序,即查找字典时遵循的查找顺序。可直接使用比较器默认的自然排序对结果进行排列
- 全排列的获取思路如下图所示(其他题解示意图):
(1)固定下标为pos
的字符,将其余字符依次进行交换,然后通过递归对下标为pos+1
的字符进行固定,最终交换至字符串尾部,排列结束
(2)为避免排列时获取重复的结果,使用Set集合保存排列结果
(3)递归操作。先固定下标为pos的位置 ,若pos = str.length() -1,说明达到字符串尾部,完成了一次全排列。再对剩余字符串进行递归,即固定pos+1的位置。- 以
“ABC”
为例,共有3个字符A、B、C
, - 若先固定pos == 0 的字符
A
,则pos+1的位置可能是B、C
,递归可得ABC、ACB
- 同理,若先固定
B
,可得到BAC、BCA
,固定C
,可得到CAB、CBA
- 以
代码
public class Solution {
public ArrayList<String> Permutation(String str) {
if(str == null){
return new ArrayList<>();
}
int n = str.length();
// Set集合存储排列结果
Set<String> set = new HashSet<>();
// 从下标0开始递归
dfs(str,0,set);
ArrayList<String> ans = new ArrayList<>(set);
// 对结果进行排序
Collections.sort(ans);
return ans;
}
public void dfs(String str,int pos,Set<String> set){
int n = str.length();
// 到达字符串尾部,完成排列
if(pos == n - 1){
set.add(str);
return;
}
//遍历字符串,判断 pos位置可能固定的字符
for(int i = pos;i < n;i++){
//先交换字符
str = swap(str,pos,i);
// 进行递归
dfs(str,pos + 1,set);
// 回溯,回到前一个状态再寻找下一种状态
str = swap(str,pos,i);
}
}
// 交换字符串指定位置的两个字符
public String swap(String str,int i,int j){
char ch = str.charAt(i);
StringBuilder sb = new StringBuilder(str);
sb.setCharAt(i,str.charAt(j));
sb.setCharAt(j,ch);
return sb.toString();
}
}