下面是从一个关于排列算法的帖子中剪出来的。觉得算法比较简洁(运用递归)。
原题如下:用1、2、2、3、4、5这六个数字,用java写一个main函数,打印出所有不同的排列,如:512234、412345等,要求: "4 "不能在第三位, "3 "与 "5 "不能相连.
Author: JianZhiZG
//===========================
本来以为很简单,用递归一下就搞定的问题,结果按照递归的常规思路,在打印的时候碰到了很麻烦的问题,费了我不少脑筋,结果答案还是很简单,弄得我做出来 了过后都准备把结果放到博客商保存了。其实我做的是字符串排列显示的问题,其中打印时的条件判断语句是根据楼主的特殊要求添加的,诸位参考:
import java.util.*;
public class test {
public static void main(String[] arg) {
Scanner r=new Scanner(System.in);
String s=r.nextLine();
Pailie(s, " ");
}
static void Pailie(String s, String p) {
if(s.length() <1) {
String t=p+s;
if(t.charAt(2)!= '4 ' && t.contains( "35 ")==false)
System.out.println(t);
}
else {
for(int i=0; i <s.length(); i++) {
Pailie(s.substring(1),p+s.substring(0,1));
s=s.substring(1)+s.substring(0,1);
}
}
}
}
//=========================
对算法的最终改进,这次应该是比较完整的版本了吧。
思路是这样的,对于任意一个串利用递归进行排列时,我们是循环串中的每个字符到第一个字符进行递归。如果串中字符出现重复的话,则重复的字符只可以利用递 归算法一次,即只要与前面相同的字符循环到第一个字符时不调用递归就可以避免重复,为此,我们只需要按如下方式修改算法:
import java.util.*;
public class test {
static int count=0;
public static void main(String[] arg) {
Scanner r=new Scanner(System.in);
String s=r.nextLine();
Pailie(s, " ");
System.out.println( "Total: "+count);
}
static void Pailie(String s,String p) {
if(s.length() <1) {
System.out.println(p);//字符串长度小于1,换行
count++;
}
else {
int index[]=new int[s.length()];
for(int i=0; i <s.length(); i++)//该循环将所有字符的第一次出现的位置记录在数组index中
index[i]=s.indexOf(s.charAt(i));
for(int i=0; i <s.length(); i++) {
if(i==index[i])//只有当循环数与第一次记录数相等时才递归,保证相同字符中的第一个调用
Pailie(s.substring(1),p+s.substring(0,1));//递归,打印其它字符
s=s.substring(1)+s.substring(0,1);//循环移位
}
}
}
}
这样,由于相同的字符只递归调用了一次,则避免了重复串的排列。下面是几个典型的运算结果:
2222222(输入。当串中的所有字符相同时,应该递归调用1次)
2222222
Total:1
原题如下:用1、2、2、3、4、5这六个数字,用java写一个main函数,打印出所有不同的排列,如:512234、412345等,要求: "4 "不能在第三位, "3 "与 "5 "不能相连.
Author: JianZhiZG
//===========================
本来以为很简单,用递归一下就搞定的问题,结果按照递归的常规思路,在打印的时候碰到了很麻烦的问题,费了我不少脑筋,结果答案还是很简单,弄得我做出来 了过后都准备把结果放到博客商保存了。其实我做的是字符串排列显示的问题,其中打印时的条件判断语句是根据楼主的特殊要求添加的,诸位参考:
import java.util.*;
public class test {
public static void main(String[] arg) {
Scanner r=new Scanner(System.in);
String s=r.nextLine();
Pailie(s, " ");
}
static void Pailie(String s, String p) {
if(s.length() <1) {
String t=p+s;
if(t.charAt(2)!= '4 ' && t.contains( "35 ")==false)
System.out.println(t);
}
else {
for(int i=0; i <s.length(); i++) {
Pailie(s.substring(1),p+s.substring(0,1));
s=s.substring(1)+s.substring(0,1);
}
}
}
}
//=========================
对算法的最终改进,这次应该是比较完整的版本了吧。
思路是这样的,对于任意一个串利用递归进行排列时,我们是循环串中的每个字符到第一个字符进行递归。如果串中字符出现重复的话,则重复的字符只可以利用递 归算法一次,即只要与前面相同的字符循环到第一个字符时不调用递归就可以避免重复,为此,我们只需要按如下方式修改算法:
import java.util.*;
public class test {
static int count=0;
public static void main(String[] arg) {
Scanner r=new Scanner(System.in);
String s=r.nextLine();
Pailie(s, " ");
System.out.println( "Total: "+count);
}
static void Pailie(String s,String p) {
if(s.length() <1) {
System.out.println(p);//字符串长度小于1,换行
count++;
}
else {
int index[]=new int[s.length()];
for(int i=0; i <s.length(); i++)//该循环将所有字符的第一次出现的位置记录在数组index中
index[i]=s.indexOf(s.charAt(i));
for(int i=0; i <s.length(); i++) {
if(i==index[i])//只有当循环数与第一次记录数相等时才递归,保证相同字符中的第一个调用
Pailie(s.substring(1),p+s.substring(0,1));//递归,打印其它字符
s=s.substring(1)+s.substring(0,1);//循环移位
}
}
}
}
这样,由于相同的字符只递归调用了一次,则避免了重复串的排列。下面是几个典型的运算结果:
2222222(输入。当串中的所有字符相同时,应该递归调用1次)
2222222
Total:1