全排列(四种方法java版本)
全排列(四种方法)1.逐步生成大法-迭代法1.1思路图解通过在每个位置上插入新字符实现全排列1.2代码实现1.2.1核心代码public ArrayList<String> getPermutation0(String A) {int n = A.length();ArrayList<String> res = new ArrayLis...
·
全排列(四种方法)
1.逐步生成大法-迭代法
1.1思路图解
通过在每个位置上插入新字符实现全排列
1.2代码实现
1.2.1核心代码
public ArrayList<String> getPermutation0(String A) {
int n = A.length();
ArrayList<String> res = new ArrayList<>();
res.add(A.charAt(0) + "");//初始化,包含第一个字符
for (int i = 1; i < n; i++) {//第二个字符插入到前面生成集合的每个元素里面
ArrayList<String> res_new = new ArrayList<>();
char c = A.charAt(i);//新字符
for (String str : res) {//访问上一趟集合中的每个字符串
// 插入到每个位置,形成一个新串
String newStr = c + str;//加在前面
res_new.add(newStr);
newStr = str + c;//加在后面
res_new.add(newStr);
//加在中间
for (int j = 1; j < str.length(); j++) {
newStr = str.substring(0, j) + c + str.substring(j);
res_new.add(newStr);
}
}
res = res_new;//更新
}
return res;
}
1.2.2完整代码(复制即可运行)
package LanQiao;
import java.util.ArrayList;
public class Demo17 {
public static void main(String[] args) {
ArrayList<String> res = new Demo17().getPermutation0("abc");
System.out.println(res.size());
System.out.println(res);
}
/*逐步生成大法-迭代法*/
public ArrayList<String> getPermutation0(String A) {
int n = A.length();
ArrayList<String> res = new ArrayList<>();
res.add(A.charAt(0) + "");//初始化,包含第一个字符
for (int i = 1; i < n; i++) {//第二个字符插入到前面生成集合的每个元素里面
ArrayList<String> res_new = new ArrayList<>();
char c = A.charAt(i);//新字符
for (String str : res) {//访问上一趟集合中的每个字符串
// 插入到每个位置,形成一个新串
String newStr = c + str;//加在前面
res_new.add(newStr);
newStr = str + c;//加在后面
res_new.add(newStr);
//加在中间
for (int j = 1; j < str.length(); j++) {
newStr = str.substring(0, j) + c + str.substring(j);
res_new.add(newStr);
}
}
res = res_new;//更新
}
return res;
}
}
1.3运行结果
2.多路递归
2.1思路图解
先确定第一个元素,后面的的再进行排序(遵循先纵后横的原则)
利用了回溯的思想,每层对括号中的每一个元素,取出来加入已经选择的集合,这样成为了下一层。
后面的层都遵循这样的逻辑,直到括号内没有元素。
但是需要保留父亲的状态才能得到其他的支路(因为父节点是共享的)
2.2代码实现
package LanQiao;
import java.util.ArrayList;
import java.util.Arrays;
/**
* 编写一个方法,确定某字符串的所有排列组合。
给定一个string A和一个int n,代表字符串和其长度,请返回所有该字符串字符的排列,
保证字符串长度小于等于11且字符串中字符均为大写英文字符,
排列中的字符串按字典序从大到小排序。(不合并重复字符串)
*/
public class Demo18 {
public static void main(String[] args) {
ArrayList<String> res = new Demo18().getPermutation("ABC");
System.out.println(res.size());
System.out.println(res);
}
ArrayList<String> res = new ArrayList<>();
public ArrayList<String> getPermutation(String A) {
char[] arr = A.toCharArray();
Arrays.sort(arr);//abc
getPermutationCore(arr, 0);
return res;
}
private void getPermutationCore(char[] arr, int k) {
if (k == arr.length) {//排好了一种情况,递归的支路走到底了
res.add(new String(arr));
}
//从k位开始的每个字符,都尝试放在新排列的k这个位置
for (int i = k; i < arr.length; i++) {
swap(arr, k, i);//把后面每个字符换到k位
getPermutationCore(arr, k + 1);
swap(arr, k, i);//回溯
}
}
//交换位置
static void swap(char[] arr, int i, int j) {
char tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
3.前缀法
思路图解
连续扫描整个字符串,将没有出现的字符串添加到集合当中(先横后纵)
代码实现
public class Demo19 {
public static void main(String[] args) {
String s = "123";
permutation("", s.toCharArray());
}
final static int k = 3;
static int count = 0;
private static void permutation(String prefix, char[] arr) {
if (prefix.length() == arr.length) {//前缀的长度==字符集的长度,一个排列就完成了
// System.out.println(prefix);
count++;
if (count == k) {
System.out.println("-------:" + prefix);
System.exit(0);
}
}
//每次都从头扫描,只要该字符可用,我们就附加到前缀后面,前缀变长了
for (int i = 0; i < arr.length; i++) {
char ch = arr[i];
//这个字符可用:在pre中出现次数<在字符集中的出现次数
if (count(prefix, ch) < count(arr, ch)) {
permutation(prefix + ch, arr);
}
}
}
//计算ch字符在整个字符串中出现的次数
private static int count(char[] arr, char ch) {
int cnt = 0;
for (char c : arr
) {
if (c == ch) cnt++;
}
return cnt;
}
private static int count(String str, char ch) {
int cnt = 0;
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) == ch) cnt++;
}
return cnt;
}
}
4.递归法
4.1思路图解
思路与迭代法类似,迭代和递归可以互相转换
4.2代码实现
package LanQiao;
import java.util.Arrays;
public class Demo20{
//s表示,从array[start]后的数据进行全排列
public static void permute(char[] array,int start){
if(start==array.length){ // 输出
System.out.println(Arrays.toString(array));
}
else
for(int i=start;i<array.length;++i){
swap(array,start,i); // 交换元素
permute(array,start+1); //交换后,再进行全排列算法
swap(array,start,i); //还原成原来的数组,便于下一次的全排列
}
}
private static void swap(char[] array,int s,int i){
char t=array[s];
array[s]=array[i];
array[i]=t;
}
public static void main(String[] args){
String s="ABC";
permute(s.toCharArray(),0);
}
}
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
已为社区贡献5条内容
所有评论(0)