package stalin; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; /** * Stalin-Sort is an impractical algorithm for bringing data structures into order. * *
* Idea by: @mathew@mastodon.social.
*
*
*
*
*
* However, this does not specify how exactly the elements are chosen. For
* example for the input [42,1,2,3,4,5,6] you just get
* [42] instead of [1,2,3,4,5,6]. You can get a better
* result if you use divide and conquer. And that is something Stalin
* would do, don't you think? So this is the recursive solution, implemented in
* Java. It tries all possible results, which is not a single pass and therefore
* defeats the purpose of having a fast algorithm. And none of these are
* in-place, so a new data structure has to be created. That's why I added an
* implementation using a {@link LinkedList}.
*
* There are 5 public static methods: *
O(n)
* O(n)
* O(n)
* because the resulting array has to be created.
*/
public static int[] sort(final int[] integers) {
var previous = Integer.MIN_VALUE;
final var accepted = new boolean[integers.length];
var newLen = 0;
for (var i = 0; i < integers.length; i++) {
final var value = integers[i];
if (previous < value) {
final var next = i + 1 < integers.length ? integers[i + 1] : Integer.MAX_VALUE;
if (next > previous && next < value) {
// Eliminate this one and keep the next one instead.
} else {
accepted[i] = true;
newLen++;
previous = value;
}
} // else: Eliminate (not accepted)
}
final var result = new int[newLen];
for (int i = 0, j = 0; i < accepted.length; i++) {
if (accepted[i])
result[j++] = integers[i];
}
return result;
}
/**
* Improved implementation of Stalin-Sort for integers to find the best
* solution. Uses divide and conquer to solve this problem. This is not
* in O(n). More like O(n logn).
*/
public static int[] sortDC(final int[] input) {
final boolean[] accepted = new boolean[input.length];
final int newLen = _sortDC(input, 0, accepted, 0, Integer.MIN_VALUE);
final var result = new int[newLen];
for (int i = 0, j = 0; i < input.length; i++) {
if (accepted[i])
result[j++] = input[i];
}
return result;
}
/**
* Recursive Stalin-Sort with divide and conquer.
*
* @param input
* the original input (never changes)
* @param position
* the position of the value to be accepted or eliminated
* @param accepted
* bit set of already accepted values, which will be updated.
* @return the length of the result. the longer one always wins.
*/
private static int _sortDC(final int[] input, final int position, final boolean[] accepted, final int count,
final int lastAccepted) {
final var len = input.length;
// System.out.println(String.format("%s = %d", Arrays.toString(accepted),
// count));
if (len == position)
return count;
if (position > 0 && input[position] < lastAccepted) {
// input[position] has to be eliminated.
return _sortDC(input, 1 + position, accepted, count, lastAccepted);
}
// First try: eliminate the value
final var accepted1 = Arrays.copyOf(accepted, len);
// accepted1[position] = false;
final int result1 = _sortDC(input, 1 + position, accepted1, count, lastAccepted);
// Second try: accept the value
final var accepted2 = Arrays.copyOf(accepted, len);
accepted2[position] = true;
final int result2 = _sortDC(input, 1 + position, accepted2, 1 + count, input[position]);
// Which one is better?
if (result2 > result1) {
System.arraycopy(accepted2, 0, accepted, 0, len);
return result2;
} else {
System.arraycopy(accepted1, 0, accepted, 0, len);
return result1;
}
}
/**
* Naive implementation of Stalin-Sort. This always creates a new list (not
* in-place!). It works but it does not return the longest possible list. Works
* great with linked lists. But no support for null.
*/
public static O(n). More like O(n logn).
*/
public static null.
*
* @param input
* the original input (never changes)
* @param position
* the position of the value to be accepted or eliminated
* @param accepted
* bit set of already accepted values, which will be updated.
* @return the length of the result. the longer one always wins.
*/
private static null.
*/
public static