128 lines
2.8 KiB
Java
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}));
|
|
}
|
|
}
|