Étant donné deux plages entières inclusives [x1: x2] et [y1: y2], où x1 ≤ x2 et y1 ≤ y2, quelle est la façon la plus efficace de tester s'il y a un chevauchement des deux plages?
Une implémentation simple est la suivante:
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);
}
Mais je m'attends à ce qu'il existe des moyens plus efficaces de calculer cela.
Quelle méthode serait la plus efficace en termes de moins d'opérations.
performance
comparison
integer
range
WilliamKF
la source
la source
Réponses:
Que signifie le chevauchement des plages? Cela signifie qu'il existe un certain nombre C qui est dans les deux gammes, à savoir
et
Maintenant, si nous sommes autorisés à supposer que les plages sont bien formées (de sorte que x1 <= x2 et y1 <= y2), il suffit de tester
la source
x1 <= y2 && y1 >= x2
, non?Étant donné deux plages [x1, x2], [y1, y2]
la source
min(x2,y2) - max(x1,y1)
fournit la quantité de chevauchement au cas où vous en auriez besoin.Cela peut facilement déformer un cerveau humain normal, j'ai donc trouvé une approche visuelle plus facile à comprendre:
le Explication
Si deux plages sont «trop grasses» pour tenir dans une fente qui est exactement la somme de la largeur des deux, elles se chevauchent.
Pour les gammes
[a1, a2]
et[b1, b2]
ce serait:la source
a2 - a1 + b2 - b1
peut déborder. Pour y remédier, réorganisez la formule enmax(a2, b2) - a2 - b2 < min(a1, b1) - a1 - b1
, ce qui simplifiemax(a1, b1) < min(a2, b2)
, en économisant de l'arithmétique et en évitant tout débordement possible (c'est la réponse d'AX-Labs ci-dessous). Dans le cas spécial où vous le savezb2-b1=a2-a1
, un autre réarrangement utile de la formule de FloatingRock estmax(a2, b2) - min(a1, b1) - (b2 - b1) < a2-a1
, qui devientabs(b1-a1) < a2 - a1
.Excellente réponse de Simon , mais pour moi, il était plus facile de penser au cas inverse.
Quand 2 plages ne se chevauchent-elles pas? Ils ne se chevauchent pas lorsque l'un commence après la fin de l'autre:
Maintenant, il est facile d'exprimer quand ils se chevauchent:
la source
Soustraire le minimum des extrémités des plages du maximum du début semble faire l'affaire. Si le résultat est inférieur ou égal à zéro, nous avons un chevauchement. Cela le visualise bien:
la source
Je suppose que la question portait sur le code le plus rapide et non le plus court. La version la plus rapide doit éviter les branches, nous pouvons donc écrire quelque chose comme ceci:
pour cas simple:
ou, dans ce cas:
la source
x1 <= y2 && y1 <= x2
n'a pas non plus de branches , en supposant un compilateur et une architecture CPU raisonnablement compétents (même en 2010). En fait, sur x86, le code généré est fondamentalement identique pour l'expression simple par rapport au code dans cette réponse.la source
x1 <= y1 && x2 >= y2 || x1 >= y1 && x2 <= y2
devrait également retourner vrai.Si vous aviez affaire à deux gammes
[x1:x2]
et à des gammes d'ordre[y1:y2]
naturel / anti-naturel en même temps où:x1 <= x2 && y1 <= y2
oux1 >= x2 && y1 >= y2
alors vous pouvez utiliser ceci pour vérifier:
ils se chevauchent <=>
(y2 - x1) * (x2 - y1) >= 0
où seulement quatre opérations sont impliquées:
la source
Si quelqu'un recherche une doublure qui calcule le chevauchement réel:
Si vous voulez quelques opérations de moins, mais quelques variables de plus:
la source
Pensez à l' inverse : comment faire en sorte que les 2 plages ne se chevauchent pas ? Étant donné
[x1, x2]
, alors[y1, y2]
devrait être à l' extérieur[x1, x2]
,y1 < y2 < x1 or x2 < y1 < y2
ce qui est équivalent ày2 < x1 or x2 < y1
.Par conséquent, la condition pour que les 2 plages se chevauchent:,
not(y2 < x1 or x2 < y1)
ce qui équivaut ày2 >= x1 and x2 >= y1
(identique à la réponse acceptée par Simon).la source
Vous avez déjà la représentation la plus efficace - c'est le strict minimum qui doit être vérifié, sauf si vous savez avec certitude que x1 <x2, etc., puis utilisez les solutions que d'autres ont fournies.
Vous devriez probablement noter que certains compilateurs optimiseront réellement cela pour vous - en retournant dès que l'une de ces 4 expressions retournera vrai. Si l'un retourne vrai, le résultat final le sera aussi - de sorte que les autres vérifications peuvent simplement être ignorées.
la source
Mon cas est différent. je veux vérifier que deux plages de temps se chevauchent. il ne doit pas y avoir de chevauchement de temps unitaire. voici l'implémentation de Go.
Cas de test
vous pouvez voir qu'il y a un motif XOR dans la comparaison des limites
la source
Voici ma version:
À moins que vous exécutiez un vérificateur de plage hautes performances sur des milliards d'entiers largement espacés, nos versions devraient fonctionner de la même manière. Mon point est, c'est la micro-optimisation.
la source