题目描述
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
链接:https://www.nowcoder.com/questionTerminal/fe6b651b66ae47d7acce78ffdd9a96c7
来源:牛客网
import java.util.*;
public class Solution {
private char [] seqs;
private Integer [] book;
//用于结果去重
private HashSet<String> result = new HashSet<String>();
/**
* 输入一个字符串,按字典序打印出该字符串中字符的所有排列。
* 例如输入字符串abc,则打印出由字符a,b,c
* 所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。 结果请按字母顺序输出。
输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。\
* @param str
* @return
*/
public ArrayList<String> Permutation(String str) {
ArrayList<String> arrange = new ArrayList<String>();
if(str == null || str.isEmpty()) return arrange;
char[] strs = str.toCharArray();
seqs = new char[strs.length];
book = new Integer[strs.length];
for (int i = 0; i < book.length; i++) {
book[i] = 0;
}
dfs(strs, 0);
arrange.addAll(result);
Collections.sort(arrange);
return arrange;
}
/**
* 深度遍历法
*/
private void dfs(char[] arrs, int step){
//走完所有可能 记录排列
if(arrs.length == step){
String str = "";
for (int i = 0; i < seqs.length; i++) {
str += seqs[i];
}
result.add(str);
return; //返回上一步
}
//遍历整个序列,尝试每一种可能
for (int i = 0; i < arrs.length; i++) {
//是否走过
if(book[i] == 0){
seqs[step] = arrs[i];
book[i] = 1;
//下一步
dfs(arrs, step + 1);
//走完最后一步 后退一步
book[i] = 0;
}
}
}
}
代码思想:
a->b->c
回退一步,step--,step == 2,到c,收回c,book[c] = 0;
回退一步,step--,step == 1,到b, 收回b, book[b] = 0,此时执行for循环到i = 2,step = 1,刚好把刚刚收回的c放进seqs[1]中
,book[c] = 1.然后进入dfs到c,将刚刚收回的b放进seqs[2]中,输出字符串。
回退一步,step--,step == 2,到c,收回c,book[c] = 0;
回退到原始的a的位置,将b放入a的位置(0号位),将a收回。进入下一个dfs,将a放入1号位,又因为book[c] = 1,所以直接输出字符串。
....
最后输出结果:
abc
acb
bac
bca
cab
cba
简单理解,地上有三个并排的位置,标记为0,1,2。一个人手里有三副扑克牌,标记为A,B,C。他从0开始往2移动,一次移动一个位置。
到0时把扑克A放进去,到1时把扑克B放进去,到2时把扑克C放进去。此时step= 2,再向后移一个位置,step = 3,此时输出字符串ABC。
往回退到2位置,取回C,又后退一个位置,取回B,把C放进1,取回1中的B,向后移动到2,把B放进2.输出字符串ACB。
回退到0,分别取回了BC,把B放入0,取回A,后移到1,把A放进1,后移,把C放进2,输出字符串BAC。
......
可以画一个递归调用树来理解,原理就是使用DFS来进行搜索和剪枝。
往回回溯时,执行代码:
book[i] = 0;
【图片转来的】
另一种解法,参考牛客网:
第三行代表Output.Swap B with C,相当于上一个方法中的把C放进B的位置,然后进入下一个DFS,把B放进C的位置。
链接:https://www.nowcoder.com/questionTerminal/fe6b651b66ae47d7acce78ffdd9a96c7
来源:牛客网
import java.util.List;
import java.util.Collections;
import java.util.ArrayList;
public class Solution {
public static void main(String[] args) {
Solution p = new Solution();
System.out.println(p.Permutation("abc").toString());
}
public ArrayList<String> Permutation(String str) {
List<String> res = new ArrayList<>();
if (str != null && str.length() > 0) {
PermutationHelper(str.toCharArray(), 0, res);
Collections.sort(res);
}
return (ArrayList)res;
}
public void PermutationHelper(char[] cs, int i, List<String> list) {
if (i == cs.length - 1) {
String val = String.valueOf(cs);
if (!list.contains(val))
list.add(val);
} else {
for (int j = i; j < cs.length; j++) {
swap(cs, i, j);
PermutationHelper(cs, i+1, list);
swap(cs, i, j);
}
}
}
public void swap(char[] cs, int i, int j) {
char temp = cs[i];
cs[i] = cs[j];
cs[j] = temp;
}
}
这个方法跟上一个方法思路一样,比上一个方法更好理解。