Skip to content

Instantly share code, notes, and snippets.

@stanio
Created January 5, 2020 02:20
Show Gist options
  • Save stanio/2c923fc55932a2b19f93bdf141792cfb to your computer and use it in GitHub Desktop.
Save stanio/2c923fc55932a2b19f93bdf141792cfb to your computer and use it in GitHub Desktop.
Permutations of an Array in Java
package net.example.math;
import java.io.PrintStream;
import java.util.Arrays;
/**
* <blockquote>
* <p>The number of permutation increases fast with <em>n</em>. While it takes
* only a few seconds to generate all permutations of ten elements, it will
* take two weeks to generate all permutations of 15 elements:</p>
* <table border="1">
* <tr><th> N </th><th> Number of permutations </th>
* <th colspan="2"> Time (assuming 1000000 permutations / second) </th></tr>
* <tr><td> 10 </td><td> 3628800 </td><td> 4 </td><td> Seconds </td></tr>
* <tr><td> 11 </td><td> 39916800 </td><td> 40 </td><td> Seconds </td></tr>
* <tr><td> 12 </td><td> 479001600 </td><td> 8 </td><td> Minutes </td></tr>
* <tr><td> 13 </td><td> 6227020800 </td><td> 104 </td><td> Minutes </td></tr>
* <tr><td> 14 </td><td> 87178291200 </td><td> 1 </td><td> Day </td></tr>
* <tr><td> 15 </td><td> 1307674368000 </td><td> 15 </td><td> Days </td></tr>
* <tr><td> 16 </td><td> 20922789888000 </td><td> 242 </td><td> Days </td></tr>
* <tr><td> 17 </td><td> 355687428096000 </td><td> 11 </td><td> Years </td></tr>
* <tr><td> 18 </td><td> 6402373705728000 </td><td> 203 </td><td> Years </td></tr>
* <tr><td> 19 </td><td> 121645100408832000 </td><td> 3857 </td><td> Years </td></tr>
* <tr><td> 20 </td><td> 2432902008176640000 </td><td> 77147 </td><td> Years </td></tr>
* </table>
* </blockquote>
*
* @see <a href="https://www.baeldung.com/java-array-permutations">Permutations of an Array in Java</a>
* @see <a href="https://en.wikipedia.org/wiki/Heap%27s_algorithm">Heap's algorithm</a>
*/
public class Permutations {
public static <T> void printAll(T[] elements) {
final int n = elements.length;
int[] indexes = new int[n];
for (int i = 0; i < n; i++) {
indexes[i] = 0;
}
printArray(elements);
int i = 0;
boolean even = (i % 2 == 0);
while (i < n) {
if (indexes[i] < i) {
swap(elements, even ? 0 : indexes[i], i);
printArray(elements);
indexes[i]++;
i = 0;
} else {
indexes[i] = 0;
i++;
even = (i % 2 == 0);
}
}
}
public static <T> void printAllRecursive(T[] elements) {
printAllRecursive(elements.length, elements);
}
static <T> void printAllRecursive(final int n, T[] elements) {
if (n == 1) {
printArray(elements);
return;
}
final int nMinus1 = n - 1;
final boolean even = (n % 2 == 0);
for (int i = 0; i < nMinus1; i++) {
printAllRecursive(nMinus1, elements);
swap(elements, even ? i : 0, nMinus1);
}
printAllRecursive(nMinus1, elements);
}
private static <T> void swap(final T[] input, final int a, final int b) {
T tmp = input[a];
input[a] = input[b];
input[b] = tmp;
}
static <T> void printArray(T[] input) {
count += 1;
if (out == null) {
return;
}
buf.append(input[0]);
for(int i = 1, len = input.length; i < len; i++) {
buf.append(',').append(input[i]);
}
buf.append(lineSeparator);
if (buf.length() >= BUF_CAP) {
out.print(buf);
buf.setLength(0);
}
}
private static long count = 0;
private static PrintStream out;
private static final int BUF_CAP = 1_000_000;
private static StringBuilder buf = new StringBuilder(BUF_CAP + 100);
private static String lineSeparator = System.getProperty("line.separator");
public static void main(String[] args) throws Exception {
String[] elements = new String[10];
for (int i = 0, len = elements.length; i < len; i++) {
elements[i] = String.valueOf(i + 1);
}
System.out.println("Permutations of " + Arrays.asList(elements));
//out = System.out;
//out = new PrintStream("permutations.txt");
//out = new PrintStream(new OutputStream() {
// @Override public void write(int b) { }
// @Override public void write(byte[] b, int off, int len) { }
//});
long startTime = System.currentTimeMillis(), elapsedTime;
printAll(elements);
//printAllRecursive(elements);
if (buf.length() > 0) {
out.print(buf);
out.flush();
}
elapsedTime = System.currentTimeMillis() - startTime;
System.out.println("Count: " + count);
System.out.println("Time: " + (elapsedTime / 1e3) + " sec");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment