Diberikan dua rentang bilangan bulat inklusif [x1: x2] dan [y1: y2], di mana x1 ≤ x2 dan y1 ≤ y2, apa cara paling efisien untuk menguji apakah ada tumpang tindih dari kedua rentang?
Implementasi sederhana adalah sebagai berikut:
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);
}
Tapi saya berharap ada cara yang lebih efisien untuk menghitung ini.
Metode apa yang paling efisien dalam hal operasi paling sedikit.
performance
comparison
integer
range
WilliamKF
sumber
sumber
Jawaban:
Apa artinya rentang tumpang tindih? Itu berarti ada beberapa angka C yang ada di kedua rentang, yaitu
dan
Sekarang, jika kita diizinkan untuk mengasumsikan bahwa rentangnya terbentuk dengan baik (sehingga x1 <= x2 dan y1 <= y2) maka cukup untuk menguji
sumber
x1 <= y2 && y1 >= x2
, bukan?Diberi dua rentang [x1, x2], [y1, y2]
sumber
min(x2,y2) - max(x1,y1)
memberikan jumlah tumpang tindih jika Anda membutuhkannya.Ini dapat dengan mudah melengkungkan otak manusia normal, jadi saya telah menemukan pendekatan visual agar lebih mudah dipahami:
le Penjelasan
Jika dua rentang "terlalu gemuk" untuk masuk dalam slot yang persis jumlah dari lebar keduanya, maka keduanya tumpang tindih.
Untuk rentang
[a1, a2]
dan[b1, b2]
ini akan menjadi:sumber
a2 - a1 + b2 - b1
bisa melimpah. Untuk memperbaikinya, atur ulang rumus untukmax(a2, b2) - a2 - b2 < min(a1, b1) - a1 - b1
, yang menyederhanakanmax(a1, b1) < min(a2, b2)
, menyimpan beberapa aritmatika dan menghindari kemungkinan meluap (ini adalah jawaban AX-Labs di bawah). Dalam kasus khusus di mana Anda tahub2-b1=a2-a1
, pengaturan ulang lain yang berguna dari formula FloatingRock adalahmax(a2, b2) - min(a1, b1) - (b2 - b1) < a2-a1
, yang menjadiabs(b1-a1) < a2 - a1
.Jawaban bagus dari Simon , tetapi bagi saya lebih mudah untuk memikirkan kasus terbalik.
Kapan 2 rentang tidak tumpang tindih? Mereka tidak tumpang tindih ketika salah satu dari mereka mulai setelah yang lain berakhir:
Sekarang mudah untuk mengekspresikan ketika mereka tumpang tindih:
sumber
Mengurangi Minimum dari ujung rentang dari Maksimum awal tampaknya melakukan trik. Jika hasilnya kurang dari atau sama dengan nol, kami memiliki tumpang tindih. Ini memvisualisasikannya dengan baik:
sumber
Saya kira pertanyaannya adalah tentang kode tercepat, bukan kode terpendek. Versi tercepat harus menghindari cabang, sehingga kita dapat menulis sesuatu seperti ini:
untuk kasus sederhana:
atau, untuk kasus ini:
sumber
x1 <= y2 && y1 <= x2
tidak memiliki cabang di dalamnya , dengan asumsi arsitektur kompiler dan CPU yang cukup kompeten (bahkan pada 2010). Pada kenyataannya, pada x86, kode yang dihasilkan pada dasarnya identik dengan ekspresi sederhana vs. kode dalam jawaban ini.sumber
x1 <= y1 && x2 >= y2 || x1 >= y1 && x2 <= y2
juga harus mengembalikan true.Jika Anda berurusan dengan, diberikan dua rentang
[x1:x2]
dan[y1:y2]
, kisaran urutan alami / anti-alami pada saat yang sama di mana:x1 <= x2 && y1 <= y2
ataux1 >= x2 && y1 >= y2
maka Anda mungkin ingin menggunakan ini untuk memeriksa:
mereka tumpang tindih <=>
(y2 - x1) * (x2 - y1) >= 0
di mana hanya empat operasi yang terlibat:
sumber
Jika seseorang mencari satu-liner yang menghitung tumpang tindih aktual:
Jika Anda ingin pasangan lebih sedikit operasi, tetapi pasangan lebih banyak variabel:
sumber
Pikirkan dengan cara terbalik : bagaimana membuat 2 rentang tidak tumpang tindih ? Diberikan
[x1, x2]
, maka[y1, y2]
harus di luar[x1, x2]
, yaituy1 < y2 < x1 or x2 < y1 < y2
yang setara dengany2 < x1 or x2 < y1
.Oleh karena itu, kondisi untuk membuat 2 rentang tumpang tindih:,
not(y2 < x1 or x2 < y1)
yang setara dengany2 >= x1 and x2 >= y1
(sama dengan jawaban yang diterima oleh Simon).sumber
Anda sudah memiliki representasi paling efisien - ini adalah minimum yang perlu diperiksa kecuali Anda tahu pasti bahwa x1 <x2 dll, kemudian gunakan solusi yang telah disediakan orang lain.
Anda mungkin harus memperhatikan bahwa beberapa kompiler benar-benar akan mengoptimalkan ini untuk Anda - dengan mengembalikan segera setelah salah satu dari keempat ekspresi tersebut mengembalikan true. Jika satu mengembalikan true, maka hasil akhirnya - jadi yang lain hanya bisa dilewati.
sumber
Kasus saya berbeda. saya ingin memeriksa dua rentang waktu yang tumpang tindih. seharusnya tidak ada tumpang tindih satuan waktu. di sini adalah implementasi Go.
Uji kasus
Anda dapat melihat ada pola XOR dalam perbandingan batas
sumber
Ini versi saya:
Kecuali jika Anda menjalankan beberapa pemeriksa rentang berkinerja tinggi pada milyaran bilangan bulat yang luas, versi kami akan melakukan hal yang sama. Maksud saya adalah, ini adalah optimasi mikro.
sumber