Java 递归地遍历数组的所有排列
我试图编写一个递归函数来生成数组的所有置换Java 递归地遍历数组的所有排列,java,algorithm,permutation,Java,Algorithm,Permutation,我试图编写一个递归函数来生成数组的所有置换 static int permus[] = new int[] { 1, 2, 3, 4, 5 }; static void testPermu(int start) { // Print it System.out.println(Arrays.toString(permus)); int k; for (int i = start + 1; i < permus.length; i++) {
static int permus[] = new int[] { 1, 2, 3, 4, 5 };
static void testPermu(int start)
{
// Print it
System.out.println(Arrays.toString(permus));
int k;
for (int i = start + 1; i < permus.length; i++) {
// swap
k = permus[start];
permus[start] = permus[i];
permus[i] = k;
testPermu(i);
// unswap
k = permus[start];
permus[start] = permus[i];
permus[i] = k;
}
}
您可以看到许多排列都丢失了
我是用Java编写的,但我会理解C、javascript或其他任何语言的示例,只要它不使用Java中不可用的库技巧。以下算法如何(以伪代码给出) 这将在每次运行时产生有效的排列。如果您想要所有可能的排列,只需在迭代时累积,那么您应该拥有所有排列 试试看
testPermu(start + 1);
另一种方法:
static ArrayList<ArrayList<Integer>> getPermutation(ArrayList<Integer> ints) {
if (ints.size() == 1) {
ArrayList<ArrayList<Integer>> list = new ArrayList<>();
list.add(ints);
return list;
} else {
ArrayList<ArrayList<Integer>> list = new ArrayList<>();
for (Integer i: ints) {
ArrayList<Integer> subList = new ArrayList<>(ints);
subList.remove(i);
ArrayList<ArrayList<Integer>> subListNew = getPermutation(subList);
for (ArrayList<Integer> _list: subListNew) {
ArrayList<Integer> local = new ArrayList<>();
local.add(i);
local.addAll(_list);
list.add(local);
}
}
return list;
}
}
静态ArrayList getPermutation(ArrayList ints){
如果(整数大小()==1){
ArrayList=新建ArrayList();
列表。添加(ints);
退货清单;
}否则{
ArrayList=新建ArrayList();
for(整数i:int){
ArrayList子列表=新的ArrayList(ints);
子列表。删除(i);
ArrayList subListNew=getPermutation(subList);
for(ArrayList\u列表:subListNew){
ArrayList local=新的ArrayList();
本地。添加(i);
local.addAll(_列表);
列表。添加(本地);
}
}
退货清单;
}
}
此方法首先选择一个元素,将其删除并获得一个子列表,然后生成子列表的排列,直到列表大小变为1。需要三个更正才能工作:
- 仅当
时才打印,否则会看到重复项(start==permus.length-1)
- 从
开始i=start
循环,而不是for
i=start+1
- 递归调用
testPermu(start+1)代码>而不是
testPermu(i)代码>
public static Integer[] permutate(int i)
{
int length = permus.length;
Integer[] result = new Integer[length];
List<Integer> chosen = new ArrayList<Integer>(Arrays.asList(permus));
int divider = 1;
for (int j=2; j<length; j++)
{
divider *= j;
}
for (int j=length; j>1; j--)
{
int index = i/divider;
result[length - j] = chosen.remove(index);
i = i - divider * (i/divider);
divider = divider / (j-1);
}
result[length -1] = chosen.remove(0);
return result;
}
公共静态整数[]置换(int i)
{
int length=permus.length;
整数[]结果=新整数[长度];
所选列表=新的ArrayList(Arrays.asList(permus));
整数除法器=1;
对于(int j=2;j1;j--)
{
int索引=i/除法器;
结果[长度-j]=已选择。删除(索引);
i=i-分隔器*(i/分隔器);
分隔器=分隔器/(j-1);
}
结果[长度-1]=已选择。删除(0);
返回结果;
}
以下是一个完整的示例:
package eric.math;
import java.util.Arrays;
public class Permute {
// swap 2 elements of an array,
void swap(int[] arr, int x, int y) {
int temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
/**
* print permutations of array
* @param arr
* original int array,
*/
void permute(int[] arr) {
permute(arr, 0, arr.length - 1);
}
/**
* print permutations of array
*
* @param arr
* original int array,
* @param i
* start index
* @param n
* end index
*/
void permute(int[] arr, int i, int n) {
int j;
if (i == n)
System.out.println(Arrays.toString(arr));
else {
for (j = i; j <= n; j++) {
swap(arr, i, j);
permute(arr, i + 1, n);
swap(arr, i, j); // backtrack
}
}
}
public static void main(String[] args) {
int arr[] = { 1, 2, 3 };
new Permute().permute(arr);
}
}
package eric.math;
导入java.util.array;
公共类排列{
//交换数组的2个元素,
无效交换(整数[]arr,整数x,整数y){
int temp=arr[x];
arr[x]=arr[y];
arr[y]=温度;
}
/**
*数组的打印置换
*@param-arr
*原始整数数组,
*/
无效排列(int[]arr){
排列(arr,0,arr.length-1);
}
/**
*数组的打印置换
*
*@param-arr
*原始整数数组,
*@param i
*起始索引
*@param n
*结束索引
*/
无效排列(int[]arr,int i,int n){
int j;
如果(i==n)
System.out.println(Arrays.toString(arr));
否则{
对于(j=i;j@Enric解决方案很好,但使用下面的解决方案,我们可以避免80次交换,而只执行24次交换
static void permutation(int[] a, int i, int j) {
for (; j < a.length && i < a.length; j++) {
int[] temp = null;
if (i != j) {
temp = swap(a, i, j);
System.out.println(Arrays.toString(temp));
}else{
temp = a;
}
permutation(temp, i + 1, i + 1);
}
}
public static void main(String[] args) {
int[] a = { 0, 1, 2, 3 };
permutation(a, 0, 0);
}
静态空位置换(int[]a,int i,int j){
对于(;j
我喜欢@Tony2009 10041方法,但可能有人想要更干净、更通用的版本:
public static <T> List<List<T>> getPermutations(List<T> list) {
if (list.size() == 1)
return Collections.singletonList(list);
List<List<T>> perms = new ArrayList<>();
for (T element: list) {
List<T> subList = new ArrayList<>(list);
subList.remove(element);
List<List<T>> subPerms = getPermutations(subList);
for (List<T> subPerm: subPerms) {
List<T> perm = new ArrayList<>();
perm.add(element);
perm.addAll(subPerm);
perms.add(perm);
}
}
return perms;
}
公共静态列表getPermutations(列表){
if(list.size()==1)
返回集合。singletonList(列表);
List perms=new ArrayList();
对于(T元素:列表){
列表子列表=新的ArrayList(列表);
子列表。删除(元素);
列表子项=getPermutations(子列表);
对于(列出子项:子项){
List perm=new ArrayList();
perm.add(元素);
perm.addAll(子项);
添加(perm);
}
}
回烫;
}
在将列表传递给getPermutations()之前对其进行排序
函数,如果您希望排列按升序排列。请参阅。我会尝试在这之后对代码建模。我不确定,但我认为您的问题可能源于使用单个静态数组。我非常确定您链接的示例在任何地方都使用相同的数组,它是通过引用传递的。我将尝试复制这种方法(似乎与我的基本相同:D)@MightyPork在这种情况下,您的问题应该标记为重复。基本原理实际上是相同的,但使用ArrayList更方便。如果您想在简单数组中实现该方法,也可以查看System.arraycopy,或者使用Arrays.asList()和list的toArray()进行转换方法
static void permutation(int[] a, int i, int j) {
for (; j < a.length && i < a.length; j++) {
int[] temp = null;
if (i != j) {
temp = swap(a, i, j);
System.out.println(Arrays.toString(temp));
}else{
temp = a;
}
permutation(temp, i + 1, i + 1);
}
}
public static void main(String[] args) {
int[] a = { 0, 1, 2, 3 };
permutation(a, 0, 0);
}
public static <T> List<List<T>> getPermutations(List<T> list) {
if (list.size() == 1)
return Collections.singletonList(list);
List<List<T>> perms = new ArrayList<>();
for (T element: list) {
List<T> subList = new ArrayList<>(list);
subList.remove(element);
List<List<T>> subPerms = getPermutations(subList);
for (List<T> subPerm: subPerms) {
List<T> perm = new ArrayList<>();
perm.add(element);
perm.addAll(subPerm);
perms.add(perm);
}
}
return perms;
}