前言:
这几天有点忙,这一个月没两天更新一次吧
题目描述
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
测试用例:
abc
对应输出应该为:
[“abc”,”acb”,”bac”,”bca”,”cab”,”cba”]
错误的输出
[“bac”,”abc”,”acb”,”bca”,”cba”,”cab”]
没有进行排序,调用一下sort就好Collections.sort(list),不必要重新写一个函数吧,那就本末倒置了。
分析:
第一种使用递归的方法来解决此题。详情见代码。比较容易懂。
第二种方法是使用一个ArrayList将各个排列结果存放其中。首先将字符串分解为字符数组,然后从大到小进行排列后再对数组元素的值进行替换。直到形成最后的“最小的排列”,此时所有排列已经存储在了ArrayList之中了。返回ArrayList即可。称这种排列方式为字典排列。形如其名,就是按照词典排列的方式,将所有“词”无重复地录入到ArrayList这个“词典”当中。
源码:
递归的方法:
import java.util.ArrayList;
import java.util.Collections;
public class Test1 {
public class Solution {
public ArrayList<String> Permutation(String str) {
ArrayList<String> list = new ArrayList<>();
if (list!=null&&str.length()!=0) {
Permutation(str.toCharArray(),0,list);
Collections.sort(list);
}
return (ArrayList<String>) list;
}
private void Permutation(char[] charArray, int i, ArrayList<String> list) {
if (i==charArray.length-1) {
String val = String.valueOf(charArray);
if (!list.contains(val)) {
list.add(val);
}
}else {
for (int j = 0; j < charArray.length; j++) {
swap(charArray,i,j);
Permutation(charArray, i+1, list);
swap(charArray,i,j);
}
}
}
private void swap(char[] charArray, int i, int j) {
char temp = charArray[i];
charArray[i] = charArray[j];
charArray[j] = temp;
}
}
}
字典排列:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
public class Test1 {
public class Solution {
public ArrayList<String> Permutation(String str) {
ArrayList<String> res = new ArrayList<>();
if (str != null && str.length() > 0) {
char[] seq = str.toCharArray();
Arrays.sort(seq); // 排列
res.add(String.valueOf(seq)); // 先输出一个解
int len = seq.length;
while (true) {
int p = len - 1, q;// 从后向前找一个seq[p - 1] < seq[p]
while (p >= 1 && seq[p - 1] >= seq[p])
--p;
if (p == 0)
break; // 已经是“最小”的排列,退出
// 从p向后找最后一个比seq[p]大的数
q = p;
--p;
while (q < len && seq[q] > seq[p])
q++;
--q;// 交换这两个位置上的值
swap(seq, q, p);
// 将p之后的序列倒序排列
reverse(seq, p + 1);
res.add(String.valueOf(seq));
}
}
return res;
}
public void reverse(char[] seq, int start) {
int len;
if(seq == null || (len = seq.length) <= start)
return;
for (int i = 0; i < ((len - start) >> 1); i++) {
int p = start + i, q = len - 1 - i;
if (p != q)
swap(seq, p, q);
}
}
public void swap(char[] cs, int i, int j) {
char temp = cs[i];
cs[i] = cs[j];
cs[j] = temp;
}
}
}
运行测试:
递归:运行时间:126ms 占用内存:13412k
字典排列:运行时间:96ms 占用内存:11864k
总结:
可以看到使用递归解决时还是占用相当多的资源的。所以如果需要做优化的话,可以将递归替换掉,虽然递归的条理更加清楚一点。