剑指offer之java篇之全排列(三)
题:全排列 比如 abc 全排列为 abc acd bac bca cab cba 总共3! n个字母则有n!种。
分析解法一:可以用字典序来完成全排列。一次排列过程为:
1) 按照以上所述需要以从小到大顺序输出,因为用的基本数据类型,很多函数要自己写,则需要先将abc排列一下就是sort一下。
2) 从后往前找到相邻中倒置的数。 比如12543 其中相邻中倒置的是25。
3) 就着上述例子来,以2为i-1,从最后往找到i,直到找出一个比i-1里大的数。 12543中最后一个3就比2大此时停止查找。
4) swap i-1里的数,跟3)找出来的结果。 12543变成 13542
5) reverse i到最后13542变成13245。注意String里面是没有reverse方法的,stringbulider里面有reverse方法,为了用reverse方法把String转为StringBulider不划算,毕竟题目给的是ArrayList<String>类型。
6) 终止这次permutation_once函数,把结果作为下一次输出。
分析解法二: 代码中执行语句里第二行对应一个for循环,第三行对应递归调用结果,第三行对应回溯之后第二行从左到右执行。
代码:
解法一:上述算法描述的Permutation_Once函数:
public static void Permutation_Once(boolean flag,int length,char[] c, ArrayList<String> res){
int i;
for (i = length - 1; i > 0; i--) { //Once_Permutation
if (c[i] > c[i - 1]) {
//Permutation_Once();
for (int j = length - 1; j > i-1; j--) {
if (c[j] > c[i - 1]) {
flag=true;
swap(c,j, i - 1);
reverse(c,i);
res.add(String.valueOf(c));
break;
}
}
}
if(flag)
break;
}
}
总的代码描述:
public static ArrayList<String> Permutation(String str) {
ArrayList<String> res=new ArrayList<>();
if(str.length()==0)
return res;
char[] c = str.toCharArray();
Arrays.sort(c);
res.add(String.valueOf(c)); //valueOf是static方法 返回String
int length=c.length;
int n=Hierarchy(length);
for(int k=n;k>0;k--) { //总共次数 n!
boolean flag=false;
Permutation_Once( flag,length,c,res);
}
return res;
}
public static void Permutation_Once(boolean flag,int length,char[] c, ArrayList<String> res){ //与c++不同形参传什么引用啊,传值调用传的只是副本啊,java这方面区别大
int i;
for (i = length - 1; i > 0; i--) { //Once_Permutation
if (c[i] > c[i - 1]) {
//Permutation_Once();
for (int j = length - 1; j > i-1; j--) {
if (c[j] > c[i - 1]) {
flag=true;
swap(c,j, i - 1);
reverse(c,i);
res.add(String.valueOf(c));
break;
}
}
}
if(flag)
break;
}
}
public static int Hierarchy(int length){
if(length==0||length==1)
return 1;
return length*Hierarchy(length-1);
}
public static 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 static void swap(char[] cs, int i, int j) {
char temp = cs[i];
cs[i] = cs[j];
cs[j] = temp;
}
解法二:递归
public class Solution {
public ArrayList<String> Permutation(String str) {
ArrayList<String> res = new ArrayList<String>();
if (str != null && str.length() > 0) {
Permutation_Recursion(res,0,str.toCharArray());
Collections.sort(res);
}
return res;
}
public void Permutation_Recursion(ArrayList<String> alist,int i,char[] c){
if(i==c.length-1){ //退出条件
String val = String.valueOf(c);
if (!alist.contains(val))
alist.add(val);
}
//执行语句
int j;
for(j=i;j<c.length;j++){
swap(c,i,j);
Permutation_Recursion(alist,i+1,c);
swap(c,i,j); //回溯
}
}
public static void swap(char[] cs, int i, int j) {
char temp = cs[i];
cs[i] = cs[j];
cs[j] = temp;
}