Si no necesita saber lo que intervalo contiene el punto (EDIT: Creo que es probable que sí, pero yo a dejar esta respuesta para los demás con esta pregunta que no lo hacen), entonces
Preprocese los intervalos calculando dos matrices B y E. B es los valores de comenzar en orden ordenado. E es los valores de fin en orden ordenado.
Para consultar un punto x, utilice la búsqueda binaria para buscar el índice mínimo i tal que B [i]> x y el menor índice j tal que E [j] ≥ x. La cantidad de intervalos [comienzo, final] que contiene x es i - j.
class Interval {
double begin, end;
}
class BeginComparator implements java.util.Comparator<Interval> {
public int compare(Interval o1, Interval o2) {
return Double.compare(o1.begin, o2.begin);
}
};
public class IntervalTree {
IntervalTree(Interval[] intervals_) {
intervals = intervals_.clone();
java.util.Arrays.sort(intervals, new BeginComparator());
maxEnd = new double[intervals.length];
initializeMaxEnd(0, intervals.length);
}
double initializeMaxEnd(int a, int b) {
if (a >= b) {
return Double.NEGATIVE_INFINITY;
}
int m = (a + b) >>> 1;
maxEnd[m] = initializeMaxEnd(a, m);
return Math.max(Math.max(maxEnd[m], intervals[m].end), initializeMaxEnd(m + 1, b));
}
void findContainingIntervals(double x, int a, int b, java.util.Collection<Interval> result) {
if (a >= b) {
return;
}
int m = (a + b) >>> 1;
Interval i = intervals[m];
if (x < i.begin) {
findContainingIntervals(x, a, m, result);
} else {
if (x <= i.end) {
result.add(i);
}
if (maxEnd[m] >= x) {
findContainingIntervals(x, a, m, result);
}
findContainingIntervals(x, m + 1, b, result);
}
}
java.util.Collection<Interval> findContainingIntervals(double x) {
java.util.Collection<Interval> result = new java.util.ArrayList<Interval>();
findContainingIntervals(x, 0, intervals.length, result);
return result;
}
Interval[] intervals;
double[] maxEnd;
public static void main(String[] args) {
java.util.Random r = new java.util.Random();
Interval[] intervals = new Interval[10000];
for (int j = 0; j < intervals.length; j++) {
Interval i = new Interval();
do {
i.begin = r.nextDouble();
i.end = r.nextDouble();
} while (i.begin >= i.end);
intervals[j] = i;
}
IntervalTree it = new IntervalTree(intervals);
double x = r.nextDouble();
java.util.Collection<Interval> result = it.findContainingIntervals(x);
int count = 0;
for (Interval i : intervals) {
if (i.begin <= x && x <= i.end) {
count++;
}
}
System.out.println(result.size());
System.out.println(count);
}
}
son los rangos ordenados, o totalmente sin restricciones? –
Supongo que la búsqueda lineal no lo cortará? Probablemente haya formas muy inteligentes de hacerlo, pero es probable que violen sus otros requisitos. ¿Alguna indicación de cuántos rangos y llaves tenemos? – delnan
No tengo clara la pregunta, pero parece que necesitará una tabla hash de pares de {key, range}. – ben