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上.移动过程中,要求任意盘子的下面要么没有盘子,要么只能有比它大的盘子.编程实现 ...
随机推荐
- MSTSC 3389 端口修改
1. 启动注册表编辑器. 2. 找到并单击以下注册表子项: 3. HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Terminal Server ...
- [转帖] kubeadm搭建kubernetes集群
http://www.bladewan.com/2018/01/02/kubernetes_install/ 学习中 kubernetes V1.9安装(附离线安装包和离线镜像) 2018-01-0 ...
- FICO基础知识(三)
成本中心: 成本中心是企业内的最小职责单位,是每一笔费用的具体接收者.创建成本中心主数据时必须将每个成本中心分配给标准层次结构的某个节点,标准层次结构反映了成本中心与成本中心.成本中心与成本中心组.成 ...
- js語句
js語句就是告訴瀏覽器要做什麼: js代碼就是js語句序列: js代碼塊就是{}包括的,函數就是一個代碼塊的典型例子: js注釋:單行注釋://,多行注釋:/**/ js對大小寫敏感: js語句可以不 ...
- linux中内存使用原理
首先介绍一下linux中内存是如何使用的. 当有应用需要读写磁盘数据时,由系统把相关数据从磁盘读取到内存,如果物理内存不够,则把内存中的部分数据导入到磁盘,从而把磁盘的部分空间当作虚拟内存 来使用,也 ...
- Js更改样式导致hover效果消失
[问题来源] 今天做单次倒计时,利用JS更改了button样式之后,再次点击时,发现hover效果消失. 原因: CSS的优先级问题导致 [解决方法] 利用!important提高hover的优先级 ...
- POJ1860(Currency Exchange)
题意: 给出一张各种货币交换的网络,问在网络中交换原有的货币,问货币能否增值? 解析: 判断是否存在正环即可 用spfa 负环和正环的判定方法一样 如果一个点的进队次数超过n次 则存在环 代码如 ...
- 通俗理解TCP/IP协议三次握手四次分手流程
转自:https://blog.csdn.net/special23/article/details/54137298 三次握手流程 客户端发个请求“开门呐,我要进来”给服务器 服务器发个“进来吧,我 ...
- BZOJ 4671 异或图 | 线性基 容斥 DFS
题面 Description 定义两个结点数相同的图 G1 与图 G2 的异或为一个新的图 G, 其中如果 (u, v) 在 G1 与 G2 中的出现次数之和为 1, 那么边 (u, v) 在 G 中 ...
- 树莓派上使用mdk3对无线热点进行DoS攻击
写在前面 你必须确保你的无线网卡支持监听模式(混淆模式),树莓派板载的无限网卡是不支持的.所以你必须额外安装一个支持监听模式的USB无线网卡. 安装mdk3 安装sudo apt install md ...