我正在尝试编写一个递归函数来生成数组的所有排列。
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;
}
}
它被调用为testPermu(0)
并且应该产生所有排列,但这不起作用。我该如何解决?
它需要递归,每次调用函数时,都应该得到一个新的排列。
现在输出
[1, 2, 3, 4, 5] [2, 1, 3, 4, 5] [2, 3, 1, 4, 5] [2, 3, 4, 1, 5] [2, 3, 4, 5, 1] [2, 3, 5, 4, 1] [2, 4, 3, 1, 5] [2, 4, 3, 5, 1] [2, 5, 3, 4, 1] [3, 2, 1, 4, 5] [3, 2, 4, 1, 5] [3, 2, 4, 5, 1] [3, 2, 5, 4, 1] [4, 2, 3, 1, 5] [4, 2, 3, 5, 1] [5, 2, 3, 4, 1]
你可以看到许多排列都缺失了。
我用Java编写它但我会理解C,javascript或其他任何例子,只要它没有使用Java中没有的一些库技巧。
答案 0 :(得分:4)
为了工作需要三次更正:
(start == permus.length-1)
时打印,否则您将看到重复项for
启动i = start
循环,而不是i = start + 1
testPermu(start + 1);
而不是testPermu(i);
答案 1 :(得分:2)
以下是一个完整的例子:
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);
}
}
答案 2 :(得分:2)
@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);
}
答案 3 :(得分: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;
}
}
此方法首先选择一个元素,删除它并获得一个子列表,然后生成子列表的排列,直到列表大小变为1。
答案 4 :(得分:0)
尝试
testPermu(start + 1);
答案 5 :(得分:0)
我喜欢@ tony200910041方法,但也许有人会想要一个更干净,更通用的版本:
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()
函数之前对其进行排序。
答案 6 :(得分:-1)
你可以在没有递归的情况下完成它
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;
}
答案 7 :(得分:-2)
以下算法(以伪代码给出)
iterate over elements:
pick one of the element at random
call function again on the remaining elements
if elements.size == 1
return or print
这应该在每次运行时产生有效的排列。如果您想要所有可能的排列,只需在迭代时累积,那么您应该拥有所有排列。