题目:输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
——来源于《剑指offer》
感谢这篇文章的作者:字符串全排列算法学习
-
解题思路:
- 我们可以先考虑特例,即字符串中没有重复字符的时候该怎么办。
- 没有重复字符的时候我们可以,固定第一位,使第一位依次与后面的各位交换。然后递归对第一位后面的子字符串进行相同操作。
- 然后我们考虑有重复项的时候:例如:对abb,第一个数a与第二个数b交换得到bab,然后考虑第一个数与第三个数交换,此时由于第三个数等于第二个数,所以第一个数就不再用与第三个数交换了。再考虑bab,它的第二个数与第三个数交换可以解决bba。此时全排列生成完毕!
-
代码实现:
import java.util.*;
/**
* @author lijing
* @date 2019-08-03 16:22
* @description 字符串全排列
*/
public class Solution {
private ArrayList<String> list = new ArrayList<>();
public ArrayList<String> Permutation(String str) {
if (str == null || str.equals("")) {
return list;
}
Permutation(str.toCharArray(), 0);
Collections.sort(list);
return list;
}
private void Permutation(char[] array, int index) {
if (index == array.length - 1) {
list.add(String.valueOf(array));
} else {
// 将交换过的字符存入set中,如果set中有上次已经交换过的字符,就不再进行交换
HashSet<Character> set = new HashSet<>();
for (int i = index; i < array.length; i++) {
if (i == index || !set.contains(array[i])) {
set.add(array[i]);
swap(array, i, index);
Permutation(array, index + 1);
// 这一步是将交换过的序列再交换回去,再进行下一次循环
swap(array, i, index);
}
}
}
}
private void swap(char[] array, int i, int j) {
char temp = array[i];
array[i] = array[j];
array[j] = temp;
}
public static void main(String[] args) {
System.out.println(new Solution().Permutation("abb"));
}
}