Эрэмбэлэгдсэн array-н дундах утгыг шалгаж, хайх хүрээгээ алхам бүрт хоёр дахин багасгадаг хурдан хайлт.
Эхлээд жижиг бодлого
Эрэмбэлэгдсэн a = [2, 5, 8, 12, 16, 23, 38, 56, 72, 91] array-гээс 23-ыг хайя. Хариу нь index 5.
Эхнээс нь нэг нэгээр нь шалгавал 6 харьцуулалт хийнэ. Binary Search ердөө 3 удаа mid-ийг шалгаад олно.
Энгийн аргаас санаа руу
Хамгийн энгийн арга бол эхнээс нь нэг нэгээр харах. n = 1 000 000 бол хамгийн муудаа сая удаа шалгана.
Гэтэл array эрэмбэлэгдсэн байгаа. Дунд байгаа a[mid]-ийг харахад л хариу аль талд байгааг мэднэ: a[mid] < x бол x зүүн хагаст байж чадахгүй тул тэр хагасыг бүхэлд нь хаяна. Алхам бүрт хайх хүрээ хоёр дахин багасна.
Нэр томьёо ба тэмдэглэгээ
- lo, hi
- Хариу байж болох хүрээний зүүн ба баруун зааг. Хоёулаа хүрээнд багтана.
- mid
- Хүрээний дунд index:
(lo + hi) / 2. - эрэмбэлэгдсэн array
- Утгууд нь багаас их рүү дараалсан array. Binary Search зөвхөн үүн дээр ажиллана.
- -1
- Хайсан тоо array-д байхгүй гэдгийг илэрхийлэх хариу.
23-ыг хайна. Эхлээд бүх array дотроос хайна: lo = 0, hi = 9.
- Space тоглуулах
- ←→ алхам
- −+ хурд
- Энгийн
- mid
- Олдсон
- Хайлтаас хасагдсан
Тоо таах тоглоом
Найз чинь 1-ээс 100 хүртэлх нэг тоо бодсон гэж бод. "50 үү, их үү, бага уу?" гэж дундаас нь асуусаар байвал 7 асуултаар олно. Binary Search яг ингэж хайдаг.
Дараа нь юу болох вэ?
Оноо 0 / 00дараалсан зөв, хамгийн их 0
Animation нэг алхам дээр зогсоно. Дараа нь код юу хийх вэ? Таагаад оноо цуглуул! Нэвтрэх хэрэггүй, оноо чинь энэ төхөөрөмж дээр хадгалагдана.
Юунд хэрэгтэй вэ?
Эрэмбэлэгдсэн их өгөгдлөөс тоог маш хурдан олох: сая тоон дотроос 20 орчим шалгалтаар олно.
Яаж ажилладаг вэ?
1. Хайх хүрээ: lo = 0, hi = n − 1. 2. Дундах index: mid = (lo + hi) / 2. 3. a[mid] = x бол олдлоо. 4. a[mid] < x бол lo = mid + 1, их бол hi = mid − 1. 5. lo > hi болвол тоо байхгүй, хариу -1. Оролт: n, n ширхэг эрэмбэлэгдсэн тоо, дараа нь хайх тоо x.
Яагаад зөв, хэр хурдан бэ?
Алхам бүрт хаясан хагаст x байх боломжгүй: a[mid] < x бол mid болон түүнээс зүүн талын бүх утга x-ээс бага. Тиймээс x array-д байгаа бол үргэлж [lo, hi] дотор үлдэнэ.
Хүрээ n, n/2, n/4 гэж багасаад нэг элемент болоход log₂ n орчим алхам хийнэ. Сая элементтэй array-д 20 хүрэхгүй удаа шалгана: хугацаа O(log n), нэмэлт санах ой O(1).
Түгээмэл алдаа
- Эрэмбэлэгдээгүй array дээр хэрэглэх. Эхлээд
sort(a, a + n)хийх ёстой. lo = midэсвэлhi = midгэж бичвэл хүрээ багасахгүй, loop дуусахгүй.mid + 1,mid - 1гэж бич.while (lo < hi)гэж бичвэл сүүлийн нэг элементийг шалгалгүй алгасна. Энэ кододlo <= hiхэрэгтэй.- Маш том index дээр
lo + hiнь int-ээс хэтэрч болно.lo + (hi - lo) / 2гэж бичвэл аюулгүй.
Хязгаарын тохиолдол
- Хайсан тоо байхгүй:
lo > hiболоход loop дуусч -1 хэвлэнэ. - Array-д ганц элемент: нэг л шалгалтаар шийдэгдэнэ.
- Хайсан тоо хамгийн эхэнд эсвэл төгсгөлд: хүрээ нэг тал руугаа шахагдаж олно.
- Ижил утга олон: энэ код аль нэгийг нь олно, заавал эхнийхийг биш. Эхнийх нь хэрэгтэй бол Lower Bound-ыг үз.
Өөрийгөө шалга
a = [1, 3, 5, 7, 9, 11, 13]дотроос 13-ыг хайхадmidхэдэн удаа шалгагдах вэ?Хариу харах
3 удаа:
mid = 3(7),mid = 5(11),mid = 6(13).1 000 000 элементтэй array-д хамгийн муудаа хэдэн удаа шалгах вэ?
Хариу харах
20 орчим.
2²⁰ ≈ 1 000 000тул хүрээг 20 удаа хуваахад нэг элемент үлдэнэ.Яагаад эрэмбэлэгдээгүй array дээр ажиллахгүй вэ?
Хариу харах
a[mid] < xүед x зүүн талд байхгүй гэж хэлэх эрх зөвхөн эрэмбэлэгдсэн үед л бий. Эрэмбэгүй бол хаясан хагаст x байж болно.
Гурван дадлага
Hint-ээ нээхээс өмнө өөрөө оролдоорой.
1.
a = [4, 9, 15, 21, 30]дотроос 21-ийг хайхадlo,hi,midямар утга авахыг алхам алхмаар бич.Hint харах
Эхлээд
lo = 0,hi = 4,mid = 2.Хариу ба тайлбар
mid = 2: 15 < 21 тулlo = 3.mid = 3: 21 олдлоо. Хариу 3.2.Тоо олдохгүй бол -1-ийн оронд тэр тоог хаана оруулбал array эрэмбэлэгдсэн хэвээр үлдэхийг хэвлэдэг болго.
Hint харах
Loop дуусахад
loхаана зогсож байгааг ажигла.Хариу ба тайлбар
Loop дуусахад
loнь x-ээс их хамгийн эхний элементийн index байна. Тиймээс -1-ийн орондlo-г хэвлэнэ.3.Ижил утга олон байж болох үед x-ээс бага биш хамгийн эхний элементийн index-ийг ол.
Hint харах
a[mid] >= xүедmidөөрөө хариу байж болно. Хадгалаад зүүн тийш үргэлжлүүлэн хай.Хариу ба тайлбар
if (a[mid] >= x) { ans = mid; hi = mid - 1; } else lo = mid + 1;Эцэст ньansхариу болно. Үүнийг Lower Bound гэдэг.
Жишээ
Оролт
10 2 5 8 12 16 23 38 56 72 91 23
Гаралт
5
Одоо өөрөө бодоод үз
Хичээл
Энэ сэдвийн хичээл удахгүй нэмэгдэнэ.