例如,在{10,6,9,7,20,19,21,18,17,16}中,结果为4。请注意,20在右侧最多具有4个较小的元素。其他元素的数量较少,例如10个元素的右侧有3个较小的元素。
import java.util.*;
import java.io.*;
class GSOR {
public static int getMaxSmallerOnRight(int[] arr, int n) {
int count = 0;
TreeSet<Integer> set = new TreeSet<Integer>();
for (int index = n - 1; index >= 0; --index) {
set.add(arr[index]);
count = Math.max(count, set.headSet(arr[index]).size());
}
return count;
}
public static void main (String[] args) {
Scanner sc=new Scanner(System.in);
int t = sc.nextInt();
while(t-->0){
int n= sc.nextInt();
int[] arr = new int[n];
for(int i=0; i<n; i++){
arr[i]= sc.nextInt();
}
System.out.println(getMaxSmallerOnRight(arr, n));
}
}
}
如何优化此代码?我的目标是不到4.192秒。
答案 0 :(得分:1)
我们可以使用分而治之的东西,这是一个示例,我没有完全证明结果是正确的,但是我相信您可以改进更多,
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();
}
}