一,问题描述

给定一个字符串,求出该字符串的全排列。

比如:"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求解全排列的更多相关文章

  1. java实现全排列输出

    java实现全排列输出 转自:http://easonfans.iteye.com/blog/517286 最近在找工作,面试java程序员或者软件工程师,在笔试的时候常常见到这么一道题:全排列 的输 ...

  2. java实现全排列

    前天上午的面试遇到了一个用java实现一串数字的全排列的题,想来想去用递归最方便,可是没有在规定的时间内完成555,今天上午有空便继续写,以下是完成后的代码: import java.util.Arr ...

  3. java字典序全排列

    import java.util.Arrays; /** *字典序全排列 *字符串的全排列 *比如单词"too" 它的全排列是"oot","oto&q ...

  4. JAVA求解线性方程组-列主元高斯消去法

    package MyMath; import java.util.Scanner; public class Gauss { /** * @列主元高斯消去法 */ static double x[]; ...

  5. HDOJ-ACM1016(JAVA) 字典序全排列,并剪枝

    转载声明:原文转自http://www.cnblogs.com/xiezie/p/5576273.html 题意: 一个环是用图中所示的n个圆组成的.把自然数1.2.…….n分别放入每个圆中,并在相邻 ...

  6. java实现全排列问题

    1.问题描述: 一组字符串的全排列,按照全排列的顺序输出,并且每行结尾无空格. 2.输入: 输入一个字符串 3.输入示例: 请输入全排列的字符串: abc 4.输出示例: a b c a c b b ...

  7. java求解第N个素数(质数)

    面试中,遇到一个题目:求解第N个素数. import java.util.Scanner; public class GetPrimeNumber { public static int NthPri ...

  8. Java求解迷宫问题:栈与回溯算法

    摘要: 使用栈的数据结构及相应的回溯算法实现迷宫创建及求解,带点JavaGUI 的基础知识. 难度: 中级 迷宫问题是栈的典型应用,栈通常也与回溯算法连用. 回溯算法的基本描述是: (1)  选择一个 ...

  9. Java求解汉诺塔问题

    汉诺塔问题的描述如下:有3根柱子A.B和C,在A上从上往下按照从小到大的顺序放着一些圆盘,以B为中介,把盘子全部移动到C上.移动过程中,要求任意盘子的下面要么没有盘子,要么只能有比它大的盘子.编程实现 ...

随机推荐

  1. 面象对象设计原则之六:迪米特原则(LeastKnowledge Principle, LKP)

    迪米特法则来自于1987年美国东北大学(Northeastern University)一个名为“Demeter”的研究项目.迪米特法则又称为最少知识原则(LeastKnowledge Princip ...

  2. Javascript中实现继承的方式

    js中实现继承和传统的面向对象语言中有所不同:传统的面向对象语言的继承由类来实现,而在js中,是通过构造原型来实现的,原型与如下几个术语有关: ①构造函数:在构造函数内部拥有一个prototype属性 ...

  3. Node 开启

    cmd    //进入命令行 D:     //指定磁盘 cd   文件路径   //指定路径 node 文件名.js       //执行文件 增补: Node执行js文件自动嵌套 (functio ...

  4. HAProxy+keepalived+MySQL 实现MHA中slave集群负载均衡的高可用

    HAProxy+keepalived+MySQL实现MHA中slave集群的负载均衡的高可用 Ip地址划分: 240    mysql_b2 242    mysql_b1 247    haprox ...

  5. Test Scenarios for image upload functionality (also applicable for other file upload functionality)

    1 check for uploaded image path2 check image upload and change functionality3 check image upload fun ...

  6. jdk1.8 HashMap的keySet方法详解

    我在看HashMap源码的时候有一个问题让我产生了兴趣,那就是HashMap的keySet方法,没有调用HashMap的有关数据的任何方法就能获取到map的所有的键,他是怎么做到的,然后我就通过模拟k ...

  7. BZOJ2004 HNOI2010公交线路(状压dp+矩阵快速幂)

    由数据范围容易想到矩阵快速幂和状压. 显然若要满足一辆公交车的相邻站台差不超过p,则每相邻p个站台中每辆车至少经过一个站台.可以发现这既是必要的,也是充分的. 开始的时候所有车是相邻的.考虑每次把一辆 ...

  8. [luogu1447][bzoj2005][NOI2010]能量采集

    题目大意 求出\(\sum_{i=1}^{n} \sum_{i=1}^{m} gcd(i,j)\times 2 -1\). 题解 解法还是非常的巧妙的,我们考虑容斥原理.我们定义\(f[i]\)表示\ ...

  9. linux 分区、目录及用途

    主要分区: 目录 建议大小 格式 描述 / 10G-20G ext4 根目录 swap <2048M swap 交换空间 /boot 200M左右 ext4 Linux的内核及引导系统程序所需要 ...

  10. android sqlite批量插入数据速度解决方案

    转自 http://hi.baidu.com/hfutonline/blog/item/62b1e4de8bdf4b2e5882dd28.html 最近在做android项目的时候遇到一个问题,应用程 ...