Вывести все перестановки массива [дубликат]
На этот вопрос уже есть ответ здесь:
- перестановка массива 9 ответов
Я работаю над программой, и у меня есть функция, которая меняет местами позиции в массиве длины, который вводится пользователем. Однако я пытаюсь понять, как вывести этот вызов функции N! раз, что бы перечислить все перестановки в функция.
Мой код для функции перестановки:
static void nextPerm(int[] A){
for( int i = (n-1); i > 0; i-- ){
if( A[i] < A[i+1] ){
A[i] = pivot;
continue;
}
if( A[i] >= A[i+1] ){
reverseArray(A);
return;
}
}
for( int i = n; i > 0; i--){
if( A[i] > pivot ){
A[i] = successor;
continue;
}
}
Swap(pivot, successor);
int[] B = new int[pivot+1];
reverseArray(B);
return;
}
Должен ли я написать цикл в функции main, что выведет это n! времена?
3 ответа:
Создание (или печать) перестановок массива гораздо проще сделать как комбинацию рекурсивно и итеративно, чем чисто итеративно. Есть, конечно, итеративные способы сделать это, но это особенно просто с комбинацией. Конкретно отметим, что существует по определению N! перестановки массива длины N-n вариантов для первого слота, N-1 вариантов для второго и т. д. Таким образом, мы можем разбить алгоритм на два шага для каждого индекса i в array .
- выберите элемент в подмассиве
arr[i....end]
, который будет являться элементомith
массива. Замените этот элемент элементом, находящимся в данный момент вarr[i]
.- рекурсивно перестановки
arr[i+1...end]
.Отметим, что это будет выполняться в O (N!), так как на 1-й вызов будет сделано N дополнительных вызовов, каждый из которых сделает N-1 дополнительный вызов и т. д. Более того, каждый элемент в конечном итоге будет находиться в каждой позиции, и до тех пор, пока будут сделаны только свопы, ни один элемент никогда не будет дублированный.
public static void permute(int[] arr){ permuteHelper(arr, 0); } private static void permuteHelper(int[] arr, int index){ if(index >= arr.length - 1){ //If we are at the last element - nothing left to permute //System.out.println(Arrays.toString(arr)); //Print the array System.out.print("["); for(int i = 0; i < arr.length - 1; i++){ System.out.print(arr[i] + ", "); } if(arr.length > 0) System.out.print(arr[arr.length - 1]); System.out.println("]"); return; } for(int i = index; i < arr.length; i++){ //For each index in the sub array arr[index...end] //Swap the elements at indices index and i int t = arr[index]; arr[index] = arr[i]; arr[i] = t; //Recurse on the sub array arr[index+1...end] permuteHelper(arr, index+1); //Swap the elements back t = arr[index]; arr[index] = arr[i]; arr[i] = t; } }
Пример ввода, вывода:
public static void main(String[] args) { permute(new int[]{1,2,3,4}); } [1, 2, 3, 4] [1, 2, 4, 3] [1, 3, 2, 4] [1, 3, 4, 2] [1, 4, 3, 2] [1, 4, 2, 3] [2, 1, 3, 4] [2, 1, 4, 3] [2, 3, 1, 4] [2, 3, 4, 1] [2, 4, 3, 1] [2, 4, 1, 3] [3, 2, 1, 4] [3, 2, 4, 1] [3, 1, 2, 4] [3, 1, 4, 2] [3, 4, 1, 2] [3, 4, 2, 1] [4, 2, 3, 1] [4, 2, 1, 3] [4, 3, 2, 1] [4, 3, 1, 2] [4, 1, 3, 2] [4, 1, 2, 3]
Я следовал этому методу большую часть времени .. (его дают Роберт Седжвик и Кевин Уэйн. ).
Однако есть и более простой способ сделать это. Может быть, вы можете работать и вокруг этогоpublic class Permutations { // print N! permutation of the characters of the string s (in order) public static void perm1(String s) { perm1("", s); } private static void perm1(String prefix, String s) { int N = s.length(); if (N == 0) System.out.println(prefix); else { for (int i = 0; i < N; i++) perm1(prefix + s.charAt(i), s.substring(0, i) + s.substring(i+1, N)); } } // print N! permutation of the elements of array a (not in order) public static void perm2(String s) { int N = s.length(); char[] a = new char[N]; for (int i = 0; i < N; i++) a[i] = s.charAt(i); perm2(a, N); } private static void perm2(char[] a, int n) { if (n == 1) { System.out.println(a); return; } for (int i = 0; i < n; i++) { swap(a, i, n-1); perm2(a, n-1); swap(a, i, n-1); } } // swap the characters at indices i and j private static void swap(char[] a, int i, int j) { char c; c = a[i]; a[i] = a[j]; a[j] = c; }
class PermutingArray { static void permutingArray(java.util.List<Integer> arrayList, int element) { for (int i = element; i < arrayList.size(); i++) { java.util.Collections.swap(arrayList, i, element); permutingArray(arrayList, element + 1); java.util.Collections.swap(arrayList, element, i); } if (element == arrayList.size() - 1) { System.out.println(java.util.Arrays.toString(arrayList.toArray())); } } public static void main(String[] args) { PermutingArray .permutingArray(java.util.Arrays.asList(9, 8, 7, 6, 4), 0); } }
Рабочий пример здесь .. IDeone Link
Фокус в том, чтобы вернуть специальное значение (
false
в коде ниже) изnextPerm
, когда это была последняя перестановка (т. е. когда массив сортируется в порядке убывания):import java.util.*; public class Main { public static boolean nextPerm(List<Integer> a) { int i = a.size() - 2; while (i >= 0 && a.get(i) >= a.get(i + 1)) i--; if (i < 0) return false; int j = a.size() - 1; while (a.get(i) >= a.get(j)) j--; Collections.swap(a, i, j); Collections.reverse(a.subList(i + 1, a.size())); return true; } ...
Затем вы можете использовать цикл (обратите внимание, что массив должен быть отсортирован в порядке возрастания изначально):
... public static void main(String[] args) { List<Integer> a = Arrays.asList(new Integer[] {1, 2, 3, 4}); do { System.out.println(a); } while (nextPerm(a)); } }
Вы можете попробовать этот код здесь: http://ideone.com/URDFsc