¿Cuál es la forma más eficaz de comprobar si dos rangos se superponen?

Resuelto WilliamKF asked hace 14 años • 19 respuestas

Dados dos rangos inclusivos [x1:x2] y [y1:y2], donde x1 ≤ x2y y1 ≤ y2, ¿cuál es la forma más eficiente de probar si existe alguna superposición de los dos rangos?

Una implementación simple es la siguiente:

bool testOverlap(int x1, int x2, int y1, int y2) {
  return (x1 >= y1 && x1 <= y2) ||
         (x2 >= y1 && x2 <= y2) ||
         (y1 >= x1 && y1 <= x2) ||
         (y2 >= x1 && y2 <= x2);
}

Pero espero que haya formas más eficientes de calcular esto.

¿Qué método sería el más eficiente en términos de menor número de operaciones?

WilliamKF avatar Jul 17 '10 06:07 WilliamKF
Aceptado

¿Qué significa que los rangos se superpongan? Significa que existe algún número C que está en ambos rangos, es decir

x1 <= C <= x2

y

y1 <= C <= y2

Para evitar confusiones, considerando los rangos son: [x1:x2] y [y1:y2]

Ahora, si se nos permite suponer que los rangos están bien formados (de modo que x1 <= x2 e y1 <= y2), entonces es suficiente probar

x1 <= y2 && y1 <= x2

O

(InicioA <= FinB) y (FinA >= InicioB)

Simon Nickerson avatar Jul 16 '2010 23:07 Simon Nickerson

Dados dos rangos [x1,x2], [y1,y2]

def is_overlapping(x1,x2,y1,y2):
    return max(x1,y1) <= min(x2,y2)
KFL avatar Oct 15 '2012 03:10 KFL

Esto puede deformar fácilmente un cerebro humano normal, por lo que encontré que un enfoque visual es más fácil de entender:

superposición de locura

la explicación

Si dos rangos son "demasiado anchos" para caber en una ranura que es exactamente la suma del ancho de ambos, entonces se superponen.

Para rangos [a1, a2]y [b1, b2]esto sería:

/**
 * we are testing for:
 *     max point - min point < w1 + w2    
 **/
if max(a2, b2) - min(a1, b1) < (a2 - a1) + (b2 - b1) {
  // too fat -- they overlap!
}
FloatingRock avatar Aug 18 '2014 17:08 FloatingRock

Gran respuesta de Simon , pero para mí fue más fácil pensar en caso contrario.

¿Cuándo no se superponen 2 rangos? No se superponen cuando uno de ellos comienza después de que termina el otro:

dont_overlap = x2 < y1 || x1 > y2

Ahora es fácil expresar cuándo se superponen:

overlap = !dont_overlap = !(x2 < y1 || x1 > y2) = (x2 >= y1 && x1 <= y2)
Konstantin Milyutin avatar Mar 02 '2016 17:03 Konstantin Milyutin