Pagini recente » Istoria paginii blog/post-nou | Diferente pentru problema/oltenesc intre reviziile 19 si 6 | Diferente pentru problema/quadratum intre reviziile 8 si 9 | Monitorul de evaluare | Diferente pentru blog/cautare-binara intre reviziile 26 si 27
Nu exista diferente intre titluri.
Diferente intre continut:
Cautarea binara e probabil primul algoritm studiat de elevii sau studentii la informatica care exemplifica tehnica divide and conquer. Ea rezolva problema gasirii unui element x in un sir sortat A. Ideea de baza e simpla: folosindu-ne de monotonia datelor putem reduce la fiecare pas problema la jumatate. Totusi aproape fiecare concurent olimpiada de informatica are cate o poveste cum a bushit o problema din cauza unei cautari binare. La fel in interviurile de programare marea majoritatea a canditatilor nu reusesc sa scrie o cautare binara care sa mearga corect pe toate cazurile.
*Buguri frecvente;*
*Buguri frecvente:*
O implementare poate avea gramada de probleme cum ar fi:
* ciclu infinit
* probleme pentru siruri in care x nu exista sau x apare de mai multe ori
* probleme cand x apare in apropiere de inceputul sau finalul sirului
*Optimizari premature*
Am vazut tot felul de variante, de exemplu unii testeaza daca a[mid] e egal cu x si scurt circuiteaza cautarea. Aceasta optimizare nu ajuta in cazul general, doar complica codul. Alta varianta e ca poti reduce ceva mai mult problema folosind hi = mid - 1 sau lo = mid + 1. Pentru mie e putin mai greu de verificat invariantul cautarii, avand un pas logic in plus. Pe langa asta cazurile in care ajungem la una din marginile sirului pot deveni mai dificile.
O solutie folosita frecvent de membrii infoarena foloseste puterile lui 2. Codul e elegant:
== code(c) |
int binary_search(int A, int val) {
int i, step, N = A.length;
for (step = 1; step < N; step <<= 1);
for (i = 0; step; step >>= 1)
if (i + step < N && A[i + step] <= val)
i += step;
return i;
}
==
Mie nu imi place aceasta varianta. Un dezavantaj e ca un programator are nu stie trucul intelege codul de mai sus mai greu.
*Cum sa implementezi o cautare binara corecta:*
Ideea de baza e ca vom folosi un invariant in bucla cautarii binare, adica o asertiune care e adevarata de fiecare data cand intram in bucla. Pentru cazul nostru acest invariant e ca lo indica spre un element care e mai mic ca x sau spre -1 si hi indica spre un element mai mare sau egal cu x sau in A.length. Pe scurt <tex>A[lo] < x \le A[hi] </tex> (consideram <tex>A[-1] = -\infty</tex> si <tex>A[A.length] = +\infty</tex>)
Aceasta abordare e detaliata in cartea Programming Pearls de Jon Bentley.
*Optimizari premature*
Am vazut tot felul de variante, de exemplu unii testeaza daca a[mid] e egal cu x si scurt circuiteaza cautarea. Aceasta optimizare nu ajuta in cazul general, doar complica codul. Alta varianta e ca poti reduce ceva mai mult problema folosind hi = mid - 1 sau lo = mid + 1. Pentru mie e putin mai greu de verificat invariantul cautarii, avand un pas logic in plus. Pe langa asta cazurile in care ajungem la una din marginile sirului pot deveni mai dificile.
O solutie folosita frecvent de membrii infoarena foloseste puterile lui 2. Codul e elegant:
== code(c) |
int binary_search(int A, int val) {
int i, step, N = A.length;
for (step = 1; step < N; step <<= 1);
for (i = 0; step; step >>= 1)
if (i + step < N && A[i + step] <= val)
i += step;
return i;
}
==
Mie nu imi place aceasta varianta. Un dezavantaj e ca un programator are nu stie trucul intelege codul de mai sus mai greu.
*Liknbaitul din titlu :)*
Daca va suparat afirmatia aroganta din titlu, va mai zic ca in 2006, Joshua Bloch, cel care a scris algoritmul de cautare binara in java.util.Arrays a 'descoperit un bug':http://googleresearch.blogspot.com/2006/06/extra-extra-read-all-about-it-nearly.html in implementare. Acest bug care aparea in majoritatea cautarilor binare sau a sortarilor prin interclasare scrise in ultimii 20 de ani. Lucrand la Google el a ajuns sa sorteze siruri de doua miliarde de numere. Astfel pasul mid = (lo + hi) / 2 a ajuns sa depaseasca Integer.MAX_VALUE care e 2147483647. Putem rezolva bugul folosind <tex>mid = lo + (hi - lo) / 2</tex> in loc de <tex>mid = (hi + lo) / 2</tex>.
Nu exista diferente intre securitate.
Topicul de forum nu a fost schimbat.