JAVA求解全排列
一,问题描述
给定一个字符串,求出该字符串的全排列。
比如:"abc"的全排列是:abc、acb、bac、bca、cab、cba
二,实现思路
采用递归的方式求解。每次先选定一个字符,然后进行“若干次”交换,求出在选定这个字符的条件下,所有的全排列,并把字符“复位”再交换回来。至此,一趟全排列完成。第二趟,选定下一个字符,然后进行“若干次”交换,求出在选定这个字符的条件下,所有的全排列,并把字符“复位”再交换回来。.....
就类似于:(参考网上的解释如下:)
设R={r1,r2,...rn}是要进行排列的n个元素.Ri=R-{ri}.集合X中元素的全排列记为
Perm(X).(ri)Perm(X)表示在全排列Perm(X)的每一个排列前加上前缀ri得到的排列
R的全排列可归纳定义如下:
当n=1时,Perm(R)=(r),其中r是集合R中唯一的元素;
当r>1时,Perm(R)由(r1)Perm(r1),(r2)Perm(r2).....(rn)Perm(rn)构成.
全排列就是从第一个数字起每个数分别与它后面的数字交换
去重的全排列就是从第一个数字起每个数分别与它后面非重复出现的数字交换,
用编程的话描述就是第i个数与第j个数交换时,要求[i,j)中没有与第j个数相等的数。
代码实现如下:使用一个LinkedList<String>保存每一种排列,如果字符串中出现有重复的字符,则此方法会求出 重复的排列数,因而LinkedList<String>会保存重复的排列。
import java.util.Collections;
import java.util.LinkedList; public class Permutation { public static void allPermutation(String str){
if(str == null || str.length() == 0)
return;
//保存所有的全排列
LinkedList<String> listStr = new LinkedList<String>(); allPermutation(str.toCharArray(), listStr, 0); print(listStr);//打印全排列
} private static void allPermutation(char[] c, LinkedList<String> listStr, int start){ if(start == c.length-1)
listStr.add(String.valueOf(c));
else{
for(int i = start; i <= c.length-1; i++)
{
swap(c, i, start);//相当于: 固定第 i 个字符
allPermutation(c, listStr, start+1);//求出这种情形下的所有排列
swap(c, start, i);//复位
}
}
} private static void swap(char[] c, int i, int j){
char tmp;
tmp = c[i];
c[i] = c[j];
c[j] = tmp;
} private static void print(LinkedList<String> listStr)
{
Collections.sort(listStr);//使字符串按照'字典顺序'输出
for (String str : listStr) {
System.out.println(str);
}
System.out.println("size:" + listStr.size());
} //hapjin test
public static void main(String[] args) {
// allPermutation("hapjin");
allPermutation("abc");
}
}
如果要想让重复的排列只保存一次,有两种方式:①改进算法,不生成重复的排列 ②用HashSet来保存排列
那当字符串中出现重复的字符时,如何生成不重复的排列?---去重的全排列就是从第一个数字起每个数分别与它后面非重复出现的数字交换
代码实现如下:(当有重复字符时,也可生成所有正确的排列(排列不会重复))
public class Permutation {
public static void allPermutation(String str){
if(str == null || str.length() == 0)
return;
//保存所有的全排列
LinkedList<String> listStr = new LinkedList<String>();
allPermutation(str.toCharArray(), listStr, 0);
print(listStr);//打印全排列
}
private static void allPermutation(char[] c, LinkedList<String> listStr, int start){
if(start == c.length-1)
listStr.add(String.valueOf(c));//System.out.println(String.valueOf(c));
else{
for(int i = start; i <= c.length-1; i++)
{
//只有当没有重叠的字符 才交换
if(!isSwap(c, start, i))
{
swap(c, i, start);//相当于: 固定第 i 个字符
allPermutation(c, listStr, start+1);//求出这种情形下的所有排列
swap(c, start, i);//复位
}
}
}
}
private static void swap(char[] c, int i, int j){
char tmp;
tmp = c[i];
c[i] = c[j];
c[j] = tmp;
}
private static void print(LinkedList<String> listStr)
{
Collections.sort(listStr);//使字符串按照'字典顺序'输出
for (String str : listStr) {
System.out.println(str);
}
System.out.println("size:" + listStr.size());
}
//[start,end) 中是否有与 c[end] 相同的字符
private static boolean isSwap(char[] c, int start, int end)
{
for(int i = start; i < end; i++)
{
if(c[i] == c[end])
return true;
}
return false;
}
//hapjin test
public static void main(String[] args) {
// allPermutation("hapjin");
allPermutation("aba");
}
}
上面的实现将所有的排列顺序都保存到LinkedList<String>了,这是要注意的。当然也可以不保存排列的顺序,直接输出(allPermutation方法)。
if(start == c.length-1)
listStr.add(String.valueOf(c));//保存排列
//System.out.println(String.valueOf(c));//不保存排列,直接输出
参考资料:全排列和全组合的实现
原文:http://www.cnblogs.com/hapjin/p/5757810.html
JAVA求解全排列的更多相关文章
- java实现全排列输出
java实现全排列输出 转自:http://easonfans.iteye.com/blog/517286 最近在找工作,面试java程序员或者软件工程师,在笔试的时候常常见到这么一道题:全排列 的输 ...
- java实现全排列
前天上午的面试遇到了一个用java实现一串数字的全排列的题,想来想去用递归最方便,可是没有在规定的时间内完成555,今天上午有空便继续写,以下是完成后的代码: import java.util.Arr ...
- java字典序全排列
import java.util.Arrays; /** *字典序全排列 *字符串的全排列 *比如单词"too" 它的全排列是"oot","oto&q ...
- JAVA求解线性方程组-列主元高斯消去法
package MyMath; import java.util.Scanner; public class Gauss { /** * @列主元高斯消去法 */ static double x[]; ...
- HDOJ-ACM1016(JAVA) 字典序全排列,并剪枝
转载声明:原文转自http://www.cnblogs.com/xiezie/p/5576273.html 题意: 一个环是用图中所示的n个圆组成的.把自然数1.2.…….n分别放入每个圆中,并在相邻 ...
- java实现全排列问题
1.问题描述: 一组字符串的全排列,按照全排列的顺序输出,并且每行结尾无空格. 2.输入: 输入一个字符串 3.输入示例: 请输入全排列的字符串: abc 4.输出示例: a b c a c b b ...
- java求解第N个素数(质数)
面试中,遇到一个题目:求解第N个素数. import java.util.Scanner; public class GetPrimeNumber { public static int NthPri ...
- Java求解迷宫问题:栈与回溯算法
摘要: 使用栈的数据结构及相应的回溯算法实现迷宫创建及求解,带点JavaGUI 的基础知识. 难度: 中级 迷宫问题是栈的典型应用,栈通常也与回溯算法连用. 回溯算法的基本描述是: (1) 选择一个 ...
- Java求解汉诺塔问题
汉诺塔问题的描述如下:有3根柱子A.B和C,在A上从上往下按照从小到大的顺序放着一些圆盘,以B为中介,把盘子全部移动到C上.移动过程中,要求任意盘子的下面要么没有盘子,要么只能有比它大的盘子.编程实现 ...
随机推荐
- static方法
http://www.cnblogs.com/dolphin0520/p/3799052.html 方便在没有创建对象的情况下来进行调用(方法/变量). 虽然在静态方法中不能访问非静态成员方法和非静态 ...
- linux系统下find命令的使用
1.find /* -name erlang 当前目录下,查找名为erlang的文件和目录 find /* -name rabbitmq-server 当前目录下,查找名为 rabbitmq-serv ...
- 洛谷P3588 [POI2015]PUS
题面 sol:说了是线段树优化建图的模板... 就是把一整个区间的点连到一个点上,然后用那个点来连需要连一整个区间的点就可以了,就把边的条数优化成n*log(n)了 #include <queu ...
- 平衡树及笛卡尔树讲解(旋转treap,非旋转treap,splay,替罪羊树及可持久化)
在刷了许多道平衡树的题之后,对平衡树有了较为深入的理解,在这里和大家分享一下,希望对大家学习平衡树能有帮助. 平衡树有好多种,比如treap,splay,红黑树,STL中的set.在这里只介绍几种常用 ...
- BZOJ3590 SNOI2013Quare(状压dp)
可能作为最优解的边双都可以这样生成:初始时边双内只有一个点,每次选取边双内部两点(可以相同)和一个当前不在边双内的点集,以该两点为起止点找一条链(当然如果两点相同就是个环)将点集串起来,加入边双.状压 ...
- BZOJ4699 树上的最短路(最短路径+dfs序+线段树+堆+并查集)
首先一般化的将下水道和塌陷看成一个东西.注意到在从源点出发的所有需要使用某条下水道的最短路径中,该下水道只会被使用一次,该下水道第一个被访问的点相同,且只会在第一个访问的点使用该下水道.这个第一个访问 ...
- Redis之发布订阅
一 什么是发布订阅 发布订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都将得到通知 Redis 发布订阅(pub/sub)是一种消息通信模式: ...
- Goldbach`s Conjecture LightOJ - 1259 (素数打表 哥德巴赫猜想)
题意: 就是哥德巴赫猜想...任意一个偶数 都可以分解成两个(就是一对啦)质数的加和 输入一个偶数求有几对.. 解析: 首先! 素数打表..因为 质数 + 质数 = 偶数 所以 偶数 - 质数 = 质 ...
- day27 多态 多继承 接口类 抽象类
简单来说:多态就是指一个相同的方法名在不同的对象调用的时候实现一样或者不一样的方法实例1: 动物类有个方法 "嚎叫" 狗类也有个方法 "嚎叫" 猫类继承了动物类 ...
- MT【15】证明无理数(1)
证明:$tan3^0$是无理数. 分析:证明无理数的题目一般用反证法,最经典的就是$\sqrt{2}$是无理数的证明. 这里假设$tan3^0$是有理数,利用二倍角公式容易得到$tan6^0,tan1 ...