Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 递归地遍历数组的所有排列_Java_Algorithm_Permutation - Fatal编程技术网

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;
}