题目描述
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则按字典序打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
输入描述:
输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。
一.图示:
二.字典序举例:
以9 6 4 8 5 2 1为例,通过字典序排序,找到下一个比它大的最小值步骤为:
- 从右边开始找,找到第一个左边值 < 相邻右边值的值
2 < 1不满足; 5 < 2不满足; 8 < 5不满足; 4 < 8满足,找到了
这个值为4,该值对应的下标index(从左边算),i=2
- 同样,再从右边开始找,找到第一个,值 > 上述点i=2对应4 的值
1 > 4不满足; 2 > 4不满足; 5 > 4满足,找到了
这个值为5,该值对应的下标index(从左边算),j=4
- 交换i=2和j=4位置上的元素;再将i=2后的所有值进行倒叙
9 6 4(i=2) 8 5(j=4) 2 1 =>swap: 9 6 5 8 4 2 1
将i=2之后的所有值,8 4 2 1进行倒叙=>reverse: 1 2 4 8
- 当值为9865421,找不到满足要求的 i ,即字典序排序,此值为后一个排序。
最终为:9 6 5 1 2 4 8,是9648521字典序排序后的值
三.结合代码:
public class Main38
{
/**
* 输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。
*/
public static ArrayList<String> permutation(String str) {
ArrayList<String> list = new ArrayList<>();
if (str == null || str.length() == 0)
return list;
char[] chars = str.toCharArray();
char[] temp = str.toLowerCase().toCharArray();
for (int i = 0; i < temp.length; i++)
{
if (temp[i] > 'z' || temp[i] < 'a')return list;
}
Arrays.sort(chars);//将字符数组按升序排列
list.add(String.valueOf(chars));//先将按升序排列后的字符串存入list中
while (true) {
int i = chars.length - 1;
int j = chars.length - 1;
//1.从字符数组最后一个字符开始往前遍历,寻找第一次chars[i-1]<chars[i]的位置
while (i >= 1 && chars[i - 1] >= chars[i]) {//i=2
i--;
}
if (i == 0) {//此时的数组已经是降序排列了(从右往左都是增的),表明全排列完成,cba这种
break;
}
//2.j从从最后一个位置开始,往前遍历,遇到大于chars[i-1]的值时停下
// 注意在遇到等于chars[i-1]的值的时候一定不要停下,不然会造成死循环(因为此时交换的是值相同的两个数)
while (j >= 0 && chars[j] <= chars[i - 1]) {
j--;
}
//3.
swap(chars, i - 1, j);//交换chars[i-1]和chars[j]的值
reverse(chars, i);//反转包括chars[i]元素在内到数组结尾的所有元素
list.add(String.valueOf(chars));
}
return list;
}
private static void reverse(char[] ch, int i) {
int left = i;
int right = ch.length-1;
while (left <= right){
char temp = ch[left];
ch[left] = ch[right];
ch[right] = temp;
left++;
right--;
}
}
private static void swap(char[] chars, int i, int j) {
char tmp = chars[i];
chars[i] = chars[j];
chars[j] = tmp;
}
public static void main(String[] args) {
ArrayList<String> list = permutation("abc");
for (String s : list) {
System.out.println(s);
}
}
}