制作并显示整数数组的所有排列

时间:2014-04-15 18:45:22

标签: java arrays algorithm

我目前正在为java创建一个Permutation类。我的这个类的一个方法是advance(),计算机将获取数组,然后显示数组的所有排列。

所以,例如,如果我给数组{0,1,2,3,4,5}或数字6,它应该从012345 ..... 543210给我。

这是我到目前为止的代码:

import java.util.*;

public class Permutation extends java.lang.Object {

public static int[] permutation;
public static int[] firstPerm;
public static int[] lastPerm;
public static int length;
public static int count;

public static void main(String[] args) {
    // TODO Auto-generated method stub

}

public Permutation(int n) {
    length = n;
    permutation = new int[length];
    for (int i = 0; i < length; i++) {
        permutation[i] = i;
    }
}

public Permutation(int[] perm) {
    length = perm.length;
    permutation = new int[length];
    boolean[] t = new boolean[length];
    for (int i = 0; i < length; i++) {
        if (perm[i] < 0 || perm[i] >= length) {
            throw new IllegalArgumentException("INVALID ELEMENT");
        }
        if (t[perm[i]]) {
            throw new IllegalArgumentException("DUPLICATE VALUES");
        }
        t[perm[i]] = true;
        permutation[i] = perm[i];
    }
}

public void advance() {

}

public int getElement(int i) {
    return permutation[i];
}

public boolean isFirstPerm() {
    firstPerm = new int[permutation.length];
    for (int i = 0; i < permutation.length; i++) {
        firstPerm[i] = permutation[i];
    }
    Arrays.sort(firstPerm);
    if (Arrays.equals(firstPerm, permutation)) {
        return true;
    } else {
        return false;
    }
}

public boolean isLastPerm() {
    lastPerm = new int[firstPerm.length];
    for (int i = 0; i < firstPerm.length; i++) {
        lastPerm[i] = firstPerm[firstPerm.length - 1 - i];
    }
    if (Arrays.equals(permutation, lastPerm)) {
        return true;
    } else {
        return false;
    }
}

public static Permutation randomPermutation(int n) {
    if (n <= 0) {
        throw new IllegalArgumentException("INVALID NUMBER");
    } else {
        length = n;
        permutation = new int[length];
        for (int i = 0; i < length; i++) {
            permutation[i] = i;
        }
        Collections.shuffle(Arrays.asList(permutation));
        return new Permutation(permutation);
    }
}

public void reset() {
    Arrays.sort(permutation);
}

public boolean isValid(int[] perm) {
    boolean[] t = new boolean[length];
    for (int i = 0; i < length; i++) {
        if (perm[i] < 0 || perm[i] >= length) {
            return false;
        }
        if (t[perm[i]]) {
            return false;
        }
    }
    return true;
}

public int[] toArray() {
    return permutation;
}

public String toString() {
    StringBuffer result = new StringBuffer();
    for (int i = 0; i < permutation.length; i++) {
        result.append(permutation[i]);
    }
    String perms = result.toString();
    return perms;
}

public static long totalPermutations(int n) {
    count = 1;
    for (int i = 1; i <= n; i++) {
        count = count * i;
    }
    return count;
}

}

正如你所看到的,advance()方法是我需要做的最后一件事,但我无法弄清楚。任何帮助都将是盛大的。

3 个答案:

答案 0 :(得分:1)

您可以采用的方法之一是:

  • 修复第一个元素并递归查找数组其余部分的所有排列。
  • 然后通过尝试其余每个元素来更改第一个元素。
  • 递归的基本情况是当你遍历整个长度以获得0个元素数组时。然后,打印它或将其添加到List,您可以在最后返回。

    public void advance() { 
        int[] temp = Arrays.copyOf(arr, arr.length);        
        printAll(0,temp);
    }
    
    private void printAll(int index,int[] temp) {
        if(index==n) { //base case..the end of array
         //print array temp here
        }           
        else {
            for(int i=index;i<n;i++) {//change the first element stepwise
                swap(temp,index,i);//swap to change 
                printAll(index+1, temp);//call recursively              
                swap(temp,index,i);//swap again to backtrack
            }       
        }
    }   
    
    private void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j]  = temp;
    }  
    

答案 1 :(得分:0)

您的代码现在的样子,听起来您希望能够在外部控制排列类,而不是仅支持按顺序打印所有排列的一个操作。

以下是如何计算排列的示例。

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Test {
        public static int factorial(int x) {
                int f = 1;
                while (x > 1) {
                        f = f * x;
                        x--;
                }
                return f;
        }

        public static List<Integer> permute(List<Integer> list, int iteration) {
                if (list.size() <= 1) return list;
                int fact = factorial(list.size() - 1);
                int first = iteration / fact;
                List<Integer> copy = new ArrayList<Integer>(list);
                Integer head = copy.remove(first);
                int remainder = iteration % fact;
                List<Integer> tail = permute(copy, remainder);
                tail.add(0, head);
                return tail;
        }

        public static void main(String[] args) throws IOException {
                List<Integer> list = Arrays.asList(4, 5, 6, 7);
                for (int i = 0; i < 24; i++) {
                    System.out.println(permute(list, i));
                }
        }
}

只是详细说明,代码背后的想法是将整数(迭代)映射到特定的排列(列表的排序)。我们将它视为排列的基本n表示,其中每个数字表示集合中的哪个元素进入所得排列的位置。

例如,如果我们置换(1,2,3,4),那么我们知道有4个!排列,并且“1”将是3中的第一个元素!其中,然后是(2,3,4)的所有排列。其中3个!新集(2,3,4)的排列,“2”将是2中的第一个元素!他们等等。

这就是为什么我们使用/和%来计算哪个元素进入结果排列的每个位置。

答案 2 :(得分:0)

这应该有效,而且它非常紧凑,唯一的缺点是它是递归的:

private static permutation(int x) {
  if (x < 1) {
    throw new IllegalArgumentException(x);
  } 
  LinkedList<Integer> numbers = new LinkedList<>();
  for (int i = 0; i < x; i++) {
    numbers.add(i);
  }
  printPermutations(numbers, new LinkedList<>());
}

private static void printPermutations(
      LinkedList<Integer> numbers, LinkedList<Integer> heads) {
  int size = numbers.size();
  for (int i = 0; i < size; i++) {
    int n = numbers.getFirst();
    numbers.removeFirst();
    heads.add(n);
    printPermutations(numbers, heads);
    numbers.add(n);
    heads.removeLast();
  }

  if (numbers.isEmpty()) {
    String sep = "";
    for (int n : heads) {
      System.out.print(sep + n);
      sep = " ";
    }
    System.out.println("");
  }
}