题目描述:将一个数组全排列后输出。
eg1:{“a”,“b”,“c”} ——>[a, b, c]、[a, c, b]、[b, a, c]、[b, c, a]、[c, a, b]、[c, b, a]
eg2:{"a", "c", "c", "d",} ——> 如下所示:
[a, c, c, d]
[a, c, d, c]
[a, d, c, c]
[c, c, a, d]
[c, c, d, a]
[c, a, c, d]
[c, a, d, c]
[c, d, a, c]
[c, d, c, a]
[d, c, c, a]
[d, c, a, c]
[d, a, c, c]
说明:当数组中有元素重复的时候,需要将排序后重复的数组给去除。
前言:关于数组的全排列网上的教程很多,可是大部分都没有处理重复元素的问题,这里我将我的思路及实现分享出来,望多多指教。
分析:当我们实现数组的全排列时,我们
1、将第一个元素和最后一个元素做交换,就可以得到一种数组排列。
2、将第二个元素和最后一个元素做交换,就可以得到一种数组排列。
…………………………
n、将第n个元素和最后一个元素做交换,即可得到一种数组排列。
通过以上分析,我们可以使用递归的思想来进行全排列,递归出口为:当 n==array.length 时递归结束。
方案一:
1、FullArangement类:核心类,主要实现数组的全排列等功能。
package stu.kx.test1_FullArrangement;
import java.util.Arrays;
/**
*
* @author 康茜
*全排列:
*将数组中的元素全排列(不能去除重复的元素)
*
*需要去除重复的元素;既然元素值是重复的,那么我们可以将问题简化,将问题分解成去除数组中重复元素和全排列数组两部分;
*/
public class FullArrangement {
public static void doFullArrangement(String[] array) {
getAllOrder(array, 0, array.length);
}
/**
*
* @param start 从start开始,到end结束来全排列数组
* @param end
*/
private static void getAllOrder(Object[] array, int start, int end) {
if(start == end) {
System.out.println(Arrays.toString(array));//使用Arrays工具类遍历输出数组元素
} else {
for(int i = start; i < end; i++) {
swap(array, start, i);//试探
getAllOrder(array, start + 1, end);
swap(array, i, start);//回溯
}
}
}
//数组中的两个元素交换位置
private static void swap(Object[] array, int i, int j) {
if(i == j) {
return;
}
Object temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
2、测试类:
package stu.kx.test1_FullArrangement;
public class Test {
public static void main(String[] args) {
String[] array = {"a","c","c","d"};
FullArrangement.doFullArrangement(array);
}
}
3、测试结果:
从以上输出结果来看,如果数组中含有重复的元素,则输出结果中会有重复的输出结果,可是我们所预期的结果并不是这样,那么我们来看看方案二。
方案二:
思路:在原先的解题思路上,增加了一个静态list<String> 该list中存储着本次全排列每次输出的数组排列的字符串形式,在每次输出之前判断该list中是否包含该数组的字符串形式,来判断结果是否重复,若重复,则不进行输出,否则,则输出。
1、FullArrangement类(核心类):处理全排列问题及结果重复问题。
package stu.kx.test1_FullArrangement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
*
* @author 康茜
*全排列(去除重复排序数组的全排序):——全排列的java实现(无重复元素)
*
*需要去除重复的元素;既然元素值是重复的,那么我们可以将问题简化,将问题分解成去除数组中重复元素和全排列数组两部分;
*/
public class FullArrangement1 {
private static List<String> list = new ArrayList<>();
public static void doFullArrangement(String[] array) {
/*
* 清空list,因为此list是静态的,因此每次排序时都需要清空,否则的话若重复调用排序的方法的话将不会去除重复的排序
*/
list.removeAll(list);
getAllOrder(array, 0, array.length);
}
/**
*
* @param start 从start开始,到end结束来全排列数组
* @param end
*/
private static void getAllOrder(Object[] array, int start, int end) {
if(start == end) {
//将数组转换成字符串,通过判断list中是否包含该字符串(数组的字符串形式) 来 判断该数组有没有被输出过,从而
//去除重复的数组排序。
String arrayStr = Arrays.toString(array);
if(!list.contains(arrayStr)) {
list.add(arrayStr);
} else {
System.out.println(arrayStr);
}
return;
//System.out.println(Arrays.toString(array));//使用Arrays工具类遍历输出数组元素
} else {
for(int i = start; i < end; i++) {
swap(array, start, i);
getAllOrder(array, start + 1, end);
swap(array, i, start);
}
}
}
//数组中的两个元素交换位置
private static void swap(Object[] array, int i, int j) {
if(i == j) {
return;
}
Object temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
2、测试类。
package stu.kx.test1_FullArrangement;
public class Test {
public static void main(String[] args) {
String[] array = {"a","c","c","d"};
FullArrangement1.doFullArrangement(array);
}
}
3、测试结果。
结果:从测试结果可以看出,全排列的结果不存在重复的结果。