programming-examples/java/Data_Structures/Permutations.java
2019-11-15 12:59:38 +01:00

128 lines
2.8 KiB
Java

import java.util.*;
public class Permutations {
public static boolean nextPermutation(int[] p) {
for (int a = p.length - 2; a >= 0; --a)
if (p[a] < p[a + 1])
for (int b = p.length - 1; ; --b)
if (p[b] > p[a]) {
int t = p[a];
p[a] = p[b];
p[b] = t;
for (++a, b = p.length - 1; a < b; ++a, --b) {
t = p[a];
p[a] = p[b];
p[b] = t;
}
return true;
}
return false;
}
public static int[] permutationByNumber(int n, long number) {
long[] fact = new long[n];
fact[0] = 1;
for (int i = 1; i < n; i++) {
fact[i] = i * fact[i - 1];
}
int[] p = new int[n];
int[] free = new int[n];
for (int i = 0; i < n; i++) {
free[i] = i;
}
for (int i = 0; i < n; i++) {
int pos = (int) (number / fact[n - 1 - i]);
p[i] = free[pos];
System.arraycopy(free, pos + 1, free, pos, n - 1 - pos);
number %= fact[n - 1 - i];
}
return p;
}
public static long numberByPermutation(int[] p) {
int n = p.length;
long[] fact = new long[n];
fact[0] = 1;
for (int i = 1; i < n; i++) {
fact[i] = i * fact[i - 1];
}
long res = 0;
for (int i = 0; i < n; i++) {
int a = p[i];
for (int j = 0; j < i; j++) {
if (p[j] < p[i]) {
--a;
}
}
res += a * fact[n - 1 - i];
}
return res;
}
public static void generatePermutations(int[] p, int depth) {
int n = p.length;
if (depth == n) {
System.out.println(Arrays.toString(p));
return;
}
for (int i = 0; i < n; i++) {
if (p[i] == 0) {
p[i] = depth;
generatePermutations(p, depth + 1);
p[i] = 0;
}
}
}
public static long nextPermutation(long x) {
long s = x & -x;
long r = x + s;
long ones = x ^ r;
ones = (ones >> 2) / s;
return r | ones;
}
public static List<List<Integer>> decomposeIntoCycles(int[] p) {
int n = p.length;
boolean[] vis = new boolean[n];
List<List<Integer>> res = new ArrayList<>();
for (int i = 0; i < n; i++) {
if (vis[i])
continue;
int j = i;
List<Integer> cur = new ArrayList<>();
do {
cur.add(j);
vis[j] = true;
j = p[j];
} while (j != i);
res.add(cur);
}
return res;
}
// Usage example
public static void main(String[] args) {
// print all permutations method 1
generatePermutations(new int[2], 1);
// print all permutations method 2
int[] p = {0, 1, 2};
int cnt = 0;
do {
System.out.println(Arrays.toString(p));
if (!Arrays.equals(p, permutationByNumber(p.length, numberByPermutation(p))) ||
cnt != numberByPermutation(permutationByNumber(p.length, cnt)))
throw new RuntimeException();
++cnt;
} while (nextPermutation(p));
System.out.println(5 == numberByPermutation(p));
System.out.println(Arrays.equals(new int[]{1, 0, 2}, permutationByNumber(3, 2)));
System.out.println(0b1101 == nextPermutation(0b1011));
System.out.println(decomposeIntoCycles(new int[]{0, 2, 1, 3}));
}
}