С учетом двух целочисленных диапазонов [x1: x2] и [y1: y2], где x1 ≤ x2 и y1 ≤ y2, какой самый эффективный способ проверить, есть ли какое-либо перекрытие двух диапазонов?
Простая реализация выглядит следующим образом:
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);
}
Но я ожидаю, что есть более эффективные способы вычислить это.
Какой метод будет наиболее эффективным с точки зрения наименьшего количества операций.
performance
comparison
integer
range
WilliamKF
источник
источник
Ответы:
Что означает перекрытие диапазонов? Это означает, что существует некоторое число C, которое находится в обоих диапазонах, т.е.
и
Теперь, если нам позволят предположить, что диапазоны правильно сформированы (так что x1 <= x2 и y1 <= y2), то достаточно проверить
источник
x1 <= y2 && y1 >= x2
, нет?Даны два диапазона [x1, x2], [y1, y2]
источник
min(x2,y2) - max(x1,y1)
обеспечивает количество совпадений, если вам это нужно.Это может легко исказить нормальный человеческий мозг, поэтому я обнаружил, что визуальный подход легче понять:
ле Объяснение
Если два диапазона «слишком толстые», чтобы поместиться в слоте, который в точности равен сумме ширины обоих, они перекрываются.
Для диапазонов
[a1, a2]
и[b1, b2]
это было бы:источник
a2 - a1 + b2 - b1
может переполниться. Чтобы исправить это, измените формулу наmax(a2, b2) - a2 - b2 < min(a1, b1) - a1 - b1
, что упрощаетmax(a1, b1) < min(a2, b2)
сохранение некоторой арифметики и предотвращение возможных переполнений (ответ AX-Labs ниже). В особом случае, когда вы знаетеb2-b1=a2-a1
, есть еще одна полезная перестановка формулы FloatingRockmax(a2, b2) - min(a1, b1) - (b2 - b1) < a2-a1
, которая становитсяabs(b1-a1) < a2 - a1
.Отличный ответ от Саймона , но мне было проще подумать об обратном случае.
Когда 2 диапазона не перекрываются? Они не перекрываются, когда один из них начинается после того, как другой заканчивается:
Теперь легко выразить, когда они перекрываются:
источник
Вычитание минимума из концов диапазонов из максимума начала, кажется, делает свое дело. Если результат меньше или равен нулю, мы имеем перекрытие. Это хорошо визуализирует это:
источник
Я предполагаю, что вопрос был о самом быстром, а не самом коротком коде. Самая быстрая версия должна избегать веток, поэтому мы можем написать что-то вроде этого:
для простого случая:
или, для этого случая:
источник
x1 <= y2 && y1 <= x2
также не содержит никаких ветвей , предполагая достаточно компетентную архитектуру компилятора и процессора (даже в 2010 году). На самом деле, на x86 сгенерированный код в основном идентичен для простого выражения и кода в этом ответе.источник
x1 <= y1 && x2 >= y2 || x1 >= y1 && x2 <= y2
что также должен вернуть истину.Если вы имели дело с заданными двумя диапазонами
[x1:x2]
и диапазонами[y1:y2]
естественного / антиестественного порядка одновременно, где:x1 <= x2 && y1 <= y2
илиx1 >= x2 && y1 >= y2
тогда вы можете использовать это, чтобы проверить:
они перекрываются <=>
(y2 - x1) * (x2 - y1) >= 0
где задействованы только четыре операции:
источник
Если кто-то ищет однострочник, который вычисляет фактическое перекрытие:
Если вы хотите на пару операций меньше, но на пару больше переменных:
источник
Подумайте наоборот : как сделать так, чтобы 2 диапазона не перекрывались ? Учитывая
[x1, x2]
, то[y1, y2]
должно быть снаружи[x1, x2]
, т.y1 < y2 < x1 or x2 < y1 < y2
Е. Что эквивалентноy2 < x1 or x2 < y1
.Следовательно, условие перекрытия двух диапазонов:
not(y2 < x1 or x2 < y1)
эквивалентноy2 >= x1 and x2 >= y1
(то же самое, что принятый ответ Саймона).источник
У вас уже есть самое эффективное представление - это тот минимум, который необходимо проверить, если вы не уверены, что x1 <x2 и т. Д., А затем используйте решения, которые предоставили другие.
Вы, вероятно, должны заметить, что некоторые компиляторы на самом деле оптимизируют это для вас - возвращая, как только любое из этих 4 выражений вернет true. Если один из них вернет true, конечный результат будет таким же, поэтому другие проверки можно просто пропустить.
источник
Мой случай другой. Я хочу проверить два временных диапазона перекрытия. не должно быть частичного совпадения времени. вот реализация Go.
Контрольные примеры
Вы можете видеть, что есть XOR шаблон в сравнении границ
источник
Вот моя версия:
Если вы не используете какой-либо высокопроизводительный инструмент проверки диапазона для миллиардов широко разнесенных целых чисел, наши версии должны работать аналогично. Я хочу сказать, что это микрооптимизация.
источник