题目来自:原文链接:(13条消息) 第十四届蓝桥杯集训——练习解题阶段(无序阶段)-Java全排列公式_红目香薰的博客-CSDN博客
!!!本文方法在遇到 两个相同其余不同 以及类似 情况时,会出现输出重复的情况!!!
本文方法只适用全不同或全相同处理
去重方法,可以通过将排序结果输入数组或字符串去重等等
五种去重方法:原文链接:(14条消息) Java 去除重复数据的五种方式_狼魂豹速的博客-CSDN博客
题目
全排列题目要求
题目解析
从字符串数组中每次选取一个元素,作为结果中的第一个元素;然后,对剩余的元素全排列
全排列
从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。当m=n时所有的排列情况叫全排列。
公式:全排列数f(n)=n!(定义0!=1)
例如:如果是对任意的三个字符进行全排列,也就是3!=6,当然,如果是相同的就只有1次
String s="我爱你";
三个字符,全排列,6中结果
我爱你
我你爱
爱我你
爱你我
你爱我
你我爱
问题分析与解题思路
1、注意字符字符串相同情况
注意无数据情况
全排列的数量是阶乘
阶乘需要递归方法实现
所以输出全部排列组合也需要递归方法
代码实现
主体代码
public static void main(String[] args) {
// TODO Auto-generated method stub
String s="祝好运";
char[] cs =s.toCharArray();
//确定是否有不同字符
for (int i = 0; i < s.length()-1; i++) {
if (cs[i]==cs[i+1]) {
System.out.println("含有相同字符");
break;
}
}
f(cs,0,s.length()-1);
System.out.println("排列组合数:"+f1(s.length())));
}
在这部分我们实现了字符串的输入、转化为char数组类型,判断字符才能是否相同、调用两个自定义函数输出排列结果和排列组合数
很好理解,难点主要是核心的交换排列程序
核心代码
交换排序部分
private static void f(char[] cs, int start, int end) {
if (start==end) {//递归终止条件
System.out.println(cs);
}
for (int i = start; i <= end; i++) {
//交换,
changeIndex(cs,i,start);
//再次函数实现递归排序
f(cs, start + 1,end);//再次循环避免重复解法
//还原,保证下一次循环
changeIndex(cs,i,start);
}
}
private static void changeIndex(char[] cs, int start, int end) {
//缓存交换
char temp = cs[start];
cs[start]=cs[end];
cs[end]=temp;
}
使用自定义函数完成,注意写递归时先写终止条件,避免死循环
递归方法也就是 多次循环,在原函数的基础上在进行多次,我们也就实现了递归方法、
最后一次交换就是回到原始状态,方便下一次循环使用
函数changeIndex就是一个简单的通过缓存媒介来交换的方法、
排列组合计数部分
private static int f1(int i) {
if(i==1) {
return 1;
}
if (i==0) {
return 1;
}
//递归阶乘
return i*f1(i-1);
}
在字符0/1的情况不适应阶乘函数(定义0!=1)
所以在这两种情况下,输出次数为1
其他情况就进行阶乘运算即可