求人応募の一環として実際のテストを受ける前に、Codilityのデモ問題を試しています。彼らが持っているデモの1つは、ディスクのアレイのディスク交差の数を数えることを含む問題です。
タスクの説明は
N個の整数の配列Aが与えられた場合、I番目のディスクが(0、I)を中心とし、半径がA [I]になるように、2D平面にN個のディスクを描画します。J≠Kであり、J番目とK番目のディスクに少なくとも1つの共通点がある場合、J番目のディスクとK番目のディスクは交差すると言います。関数を記述します:class Solution {public int number_of_disc_intersections(int [] A); 上で説明したようにN個のディスクを記述する配列Aが与えられると、交差するディスクのペアの数を返します。
ここでテストを表示できます。
やや明白なO(n ^ 2)時間計算量の解決策がありますが、目的はO(n * log(n))です。
私が提供したすべての例で機能するこれと、codility([1、5、2、1、4、0])によって与えられた単純なテストケースを思いついたが、Codilityはほとんどの場合失敗すると言っている他の人が、私は理由がよくわかりません。
n個のディスクのそれぞれをTreeSetに追加するのはlognであるため、これは確かにO(n log n)である必要があります。次に、O(1)操作TreeSet.headSet()のみを使用して、各ディスクをウォークスルーします。
import java.util.*;
class Circle implements Comparable<Circle> {
long edge;
int index;
Circle (long e, int i){
edge = e;
index = i;
}
long getRightAssumingEdgeIsLeft(){
return (long)(2*index - edge + 1);
}
@Override
public int compareTo(Circle other){
return Long.valueOf(edge).compareTo(other.edge);
}
}
class Solution {
public int number_of_disc_intersections ( int[] A ) {
int N = A.length;
if (N<2) return 0;
int result = 0;
SortedSet<Circle> leftEdges = new TreeSet<Circle>();
for (int i=0; i<N; i++) {
leftEdges.add( new Circle( (long)(i-A[i]), i ) );
}
int counter = 0;
for (Circle c : leftEdges) {
long rightEdge = c.getRightAssumingEdgeIsLeft();
Circle dummyCircle = new Circle (rightEdge, -1);
SortedSet<Circle> head = leftEdges.headSet(dummyCircle);
result += head.size() - counter;
if (result > 10000000) return -1;
counter++;
}
return result;
}
}