мы можем использовать вещи «Разделяй и властвуй», вот пример, который я не полностью доказал, что результаты верны, но я уверен, что вы можете улучшить еще больше,
public class GSOR extends RecursiveTask<Integer> {
private int[] arr;
private int start;
private int end;
public GSOR(int[] arr, int start, int end) {
if (end < start) {
throw new IllegalArgumentException("end < start");
}
this.arr = arr; // we do not modify the original array,
// so ref-var is OK here
this.start = start;
this.end = end;
}
@Override
protected Integer compute() {
// decide if we divide the computation by two
int middle = (end - start) / 2;
if (middle > 1) {
// fork the first half and start another task for it
ForkJoinTask<Integer> rightTask = new GSOR(arr, start, start + middle);
rightTask.fork();
return Math.max(
// just compute the second half part and find the max of them
new GSOR(arr, start + middle + 1, end).compute(),
rightTask.join()); // wait for first half's computation
}
// the items we need to deal are small enough to compute
int max = 0;
for (int i = start; i <= end; i++) {
// no duplicate item please
Set<Integer> minSets = new HashSet<>();
// it could be a long way to go if start is really beginning of the start
// if N goes to very big number we consider to divide this computation also
for (int j = i + 1; j < arr.length; j++) {
if (arr[i] > arr[j]) {
minSets.add(arr[j]);
}
}
max = Math.max(max, minSets.size());
}
return max;
}
private static ForkJoinPool fjPool = new ForkJoinPool();
public static void stop() {
fjPool.shutdown();
try {
fjPool.awaitTermination(30, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void submit(int[] arr) {
if (null == arr || arr.length < 3) {
// i can do this on my mind
return;
}
for(int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + ", ");
}
System.out.println();
Future<Integer> result = fjPool.submit(new GSOR(arr, 0, arr.length));
try {
System.out.println(result.get(5, TimeUnit.SECONDS));
} catch (InterruptedException | ExecutionException | TimeoutException e) {
e.printStackTrace();
}
}
}
, и это тестер ;
public class StackOverflowMain {
public static void main(final String[] args) {
for (int lmt = 4; lmt < 20; lmt += 3) {
int[] ints = Stream
.generate(()->Integer.valueOf((int)(Math.random()*1000)))
.limit(lmt)
.mapToInt(i -> i)
.toArray();
GSOR.submit(ints);
}
int[] arr = new int[]{10, 6, 9, 7, 20, 19, 21, 18, 17, 16};
GSOR.submit(arr);
GSOR.stop();
}
}