Algoritmul este descoperit de un tip pe nume Tarjan. Nu ma intrebati
de ce natie este si cati ani are, ca nu stiu. Algoritmul este extrem
de simplu si de elegant, plus ca nu foloseste memorie suplimentara:
pornim de la primul ghiseu cu doi pointeri X si Y. X avanseaza cu un
pas la fiecare moment de timp, iar Y avanseaza cu cate doi pasi. In
acest fel, daca lista este liniara, atunci Y ajunge la ultimul ghiseu,
apoi la 0, iar daca lista este ciclica, atunci Y o ia inaintea lui X,
apoi il intrece "cu un tur" si la un moment dat se va suprapune din
nou peste el. Tocmai acest eveniment il pandim si noi pentru a ne da
seama daca lista e ciclica sau nu.
In ambele cazuri (lista ciclica/liniara), X parcurge nodurile cel mult
o data, iar Y cel mult de doua ori. Daca lista este ciclica, pornim
din orice punct al ciclului si ne invartim dupa coada pana ajungem de
unde am plecat, parcurgand cel mult inca o data nodurile pentru a afla
lungimea ciclului. In orice caz, per total nu depasim 4*N parcurgeri
de noduri.
Se poate pune intrebarea: vreau sa numar cate noduri are ciclul, dar
cum ma asigur ca nodul din care incep numararea nu este un nod din
afara ciclului ? Respectand algoritmul lui Tarjan, este imediat
vizibil ca nodul in care Y il prinde din urma pe X este un nod din
acest ciclu.
Am in continuare un sentiment nelamurit ca problema se putea rezolva
si cu o limita de 3*N noduri, dar prefer sa arunc pisica moarta la voi
in curte decat sa-mi mai bat capul. Daca are cineva vreo idee (sau
vreo completare de orice fel, este binevenit sa o posteze.
Il rog in mod special pe Catalin Alexandru sa posteze algoritmul sau,
care mi s-a parut original. Poate pentru ca nu l-am inteles :)
|
|