Sunteți pe pagina 1din 17

Anex

9. Analiza complexitii algoritmilor

Exist mai muli algoritmi de rezolvare a unei probleme date. Prin urmare, se impune o analiz a acestora, n scopul determinrii eficienei algoritmilor de rezolvare a problemei i pe ct posibil a optimalitii lor. Criteriile n funcie de care vom stabili eficiena unui algoritm sunt complexitatea spaiu i complexitatea timp. Prin complexitate spaiu nelegem dimensiunea spaiului de memorie utilizat de program. Un program necesit un spaiu de memorie constant, independent de datele de intrare, pentru memorarea codului su, a constantelor, a variabilelor simple i a structurilor de date de dimensiune constant alocate static i un spaiu de memorie variabil, a crui dimensiune depinde adesea de datele de intrare, constnd din spaiul necesar pentru structurile de date alocate dinamic, a cror dimensiune depinde de instana problemei de rezolvat i din spaiul de memorie necesar apelurilor de proceduri i funcii. De exemplu, s considerm urmtoarea problem: Fie A o mulime cu n elemente i x o valoare de tipul elementelor mulimii A. S se decid dac x aparine sau nu mulimii. Vom scrie o funcie iterativ care va cuta secvenial valoarea x n vectorul folosit pentru memorarea mulimii A, funcie care ntoarce valoarea true dac x se gsete n vector i false n caz contrar.
function cauta : boolean; var i: integer; gasit: boolean; begin i := 1; gasit := false; while (i n) and not gasit do if a[i] = x then gasit := true else i := i+1; cauta := gasit; end;
249

Funcia cauta va fi apelat o singur dat. Neavnd parametri, va necesita spaiu de memorie doar pentru variabilele locale i pentru adresa de revenire. Deci nu este necesar spaiu de memorie variabil. Aceeai problem o putem rezolva cu ajutorul unei funcii recursive rcauta. Funcia are un parametru ntreg care indic poziia de la care ncepe cutarea n vectorul a. Evident, iniial apelm rcauta(1). function rcauta (poz: integer): boolean; begin if poz > n then rcauta := false else if a [poz] = x then rcauta := true else rcauta := rcauta(poz+1); end; Spaiul de memorie utilizat pentru un apel al funciei este cel necesar pentru memorarea parametrului (2 octei) i pentru adresa de revenire (2 octei). Dac x nu se gsete n vector se fac n apeluri recursive, deci spaiul de memorie variabil este de 4n octei. Dac x se gsete n vector, dimensiunea spaiului de memorie variabil depinde de poziia pe care x se gsete n vectorul a. Deci, varianta recursiv necesit un spaiu de memorie mult mai mare dect varianta iterativ. Progresele tehnologice fac ca importana criteriului spaiu de memorie utilizat s scad, prioritar devenind criteriul timp. Prin complexitate timp nelegem timpul necesar execuiei programului. nainte de a evalua timpul necesar execuiei programului ar trebui s avem informaii detaliate despre sistemul de calcul folosit. Pentru a analiza teoretic algoritmul, vom presupune c se lucreaz pe un calculator "clasic", n sensul c o singur instruciune este executat la un moment dat.
250

Astfel, timpul necesar execuiei programului depinde de numrul de operaii elementare efectuate de algoritm. Privind din perspectiva calculului paralel, acest mod de analiz a complexitii timp a unui algoritm va fi, probabil, total inadecvat pentru viitoarele generaii de calculatoare. Dar pentru algoritmii "clasici" ofer un criteriu general de comparaie, fr a fi necesar implementarea i rularea pe un calculator. De altfel, din motive practice, pe calculator nu putem testa algoritmul pentru cazuri orict de mari i nu putem obine informaii asupra comportrii n timp a algoritmilor dect pentru seturi particulare de date de intrare. Primul pas n analiza complexitii timp a unui algoritm este determinarea operaiilor elementare efectuate de algoritm i a costurilor acestora. Numim operaie elementar o operaie al crei timp de execuie este independent de datele de intrare ale problemei. Timpul necesar execuiei unei operaii elementare poate fi diferit de la o operaie la alta, dar este fixat, deci putem spune c operaiile elementare au timpul mrginit superior de o constant. Fr a restrnge generalitatea, vom presupune c toate operaiile elementare au acelai timp de execuie, fiind astfel necesar doar evaluarea numrului de operaii elementare, nu i a timpului total de execuie a acestora. Analiza teoretic ignor toi factorii care depind de main sau de limbajul de programare ales i se axeaz doar pe determinarea ordinului de mrime a numrului de operaii elementare. Scopul analizei teoretice a algoritmilor este de fapt determinarea unor funcii care s limiteze superior, respectiv inferior comportarea n timp a algoritmului. Funciile depind de caracteristicile relevante ale datelor de intrare. 9.1. Notaia asimptotic Notm TA(n) timpul necesar execuiei algoritmului

A.

251

Fie f: N R+* o funcie arbitrar. Spunem c algoritmul este de ordinul lui f(n) ( notat O(f(n)) ), dac i numai dac exist c > 0 i n 0N, astfel nct TA(n) c.f(n), n n . De exemplu: a) Dac TA(n) = 3n+2, atunci TA(n)O(n), pentru c 3n+2 4n, n 2. Mai general, dac TA(n) = an+b, a > 0, atunci TA(n)O(n) pentru c exist c = a+1 > 0 i n0 = bN, astfel nct an+b (a+1)n, n b. b) Dac TA(n) = 10n2+4n+2, atunci TA(n)O(n2), pentru c 10n2+4n+2 11n2, n 5. Mai general, dac TA(n) = an2+bn+c, a > 0, atunci TA(n)O(n2), pentru c an2+bn+c (a+1)n2, n max(b,c)+1. c) Dac TA(n) = 6 2n+n2, atunci TA(n)O(2n), pentru c TA(n) = 6 2n+n2 72n,n 4. Propoziie Dac TA(n) = aknk+ak-1nk-1+...+a1n+a0, atunci TA(n)O(nk). Demonstraie : TA(n) = |TA(n)| = |aknk+ak-1nk-1+...+a1n+a0| |ak|nk+|ak-1| nk-1+...+|a1|n+|a0| (|ak|+|ak-1|+...+|a1|+|a0|)nk, n 1. Alegnd c = |ak|+|ak-1|+...+|a1|+|a0| i n0 = 1 TA(n)O(nk). Q.E.D. Observaii 1. Notaia O ofer o limit superioar a timpului de execuie a unui algoritm. 2. Un algoritm cu TA(n)O(1) necesit un timp de execuie constant.
0

252

Un algoritm cu TA(n)O(n) se numete liniar. Dac TA(n)O(n2) algoritmul se numete ptratic, iar dac T (n)O(n3), cubic. Un algoritm cu T (n)O(nk) se numete polinomial, iar dac TA(n)O(2n) algoritmul se numete exponenial. 3. Notaia asimptotic O definete o relaie de ordine parial pe mulimea algoritmilor : O(1)O(log n)O(n)O(n log n)O(n2)O(nk)O(2n), k>2. Putem astfel clasifica algoritmii din punctul de vedere al performanei. Figura de mai jos ilustreaz comportarea a cinci din cele mai importante funcii de complexitate. Observai c funciile de O(n) i O(log n) cresc mult mai lent dect celelalte, n timp ce un algoritm exponenial va putea fi folosit n practic doar pentru valori mici ale lui n. Dac T A(n)O(2n), pentru n=40, pe un calculator care face 1 bilion (10 9) de operaii pe secund, sunt necesare aproximativ 18 minute. Pentru n=50, acelai program va rula 13 zile pe acest calculator, iar pentru n=60, vor fi necesari peste 310 ani, iar pentru n=100 aproximativ 4.1013 ani. Utilitatea algoritmilor polinomiali de grad mare este de asemeni limitat. De exemplu, pentru O(n 10), pe un calculator care execut 1 bilion de operaii pe secund sunt necesare 10 secunde pentru n=10, aproximativ 3 ani pentru n=100 i circa 3 .1013 ani pentru n=1000.
O(n) (linia r) 1 2 4 8 16 O(log(n)) (logaritm ic) 0 1 2 3 4 O(n.log(n )) (logliniar) 0 2 8 24 64 O(n2) (ptrati c) 1 4 16 64 256 253 O(2n) (exponen ial) 2 4 16 256 65536 O(n!) (factorial) 1 2 24 40326 20922789888 A A

32

160

1024

42949672 96

000 26313.1033

Uneori este util s determinm i o limit inferioar pentru timpul de execuie a unui algoritm. Notaia matematic este . Definiie Spunem c TA(n)(f(n)) dac i numai dac c>0 i n0N astfel nct TA(n) c f(n) ,n n0. De exemplu : a) dac TA(n) = 3n+2, atunci T A(n)(n), pentru c 3n+2 3n, n 1; b) dac TA(n) = 10n2+4n+2, atunci TA(n)(n), pentru c 10n2+4n+2 n2, n 1; c) dac T (n) = 6.2n+n2, atunci T (n)(2n), pentru c 6.2n+n2 2n, n 1. Observaie Exist funcii f care constituie att o limit superioar ct i o limit inferioar a timpului de execuie a algoritmului. Propoziie Dac TA(n) = aknk+ak-1nk-1+...+a1n+a0, ak >0 atunci TA(n)(nk). Demonstraie : ak ak aknk + ak 1nk1+...+ a1n + a0 = nk + ( nk + ak 1nk1+...+ a1n + a0) = 2 2 ak k a k a k 1 a 1 a 0 = n + nk ( + +...+ + ) 2 2 n nk1 nk 2k ak Aleg n0 N, n0 max ai , i = 01 , ,..., k 1 [i c = ak 2 Q.E.D. Definiie Spunem c TA(n)(f(n)) dac i numai dac c1, c >0 i n0N astfel nct c .f(n) T (n) c .f(n) ,n n0.
A A

254

n acest caz f(n) constituie att o limit inferioar ct i o limit superioar pentru timpul de execuie a algoritmului. Din acest motiv se poate numi ordin exact. (f(n))=O(f(n)) (f(n)). Observaie Dac TA(n) = aknk+ak-1nk-1+...+a1n+a0, ak>0 atunci TA(n) (nk). 9.2. Cazul mediu i cazul cel mai defavorabil Am artat c timpul de execuie al unui algoritm este direct proporional cu numrul de operaii elementare i am stabilit o notaie asimptotic pentru timpul de execuie. Totui, numrul de operaii elementare efectuate de algoritm poate varia considerabil pentru diferite seturi de date de intrare.Vom exprima numrul de operaii elementare ca o funcie de anumite caracteristici ale datelor de intrare (de exemplu, numrul de date de intrare sau ordinul de mrime a unei anumite date de intrare). De altfel, pentru a stabili semnificaia exact a noiunii de operaie elementar n contextul algoritmului pe care l analizm trebuie s specificm care sunt caracteristicile datelor de intrare n funcie de care estimm timpul de execuie a algoritmului. O operaie elementar este o secven computaional independent de caracteristici (de exemplu, 10 adunri pot constitui o operaie elementar, dar dac n este o caracteristic relevant a datelor de intrare, n adunri nu constituie o operaie elementar). Determinarea complexitii timp a algoritmului ca o funcie de caracteristicile datelor de intrare este o sarcin uoar doar pentru algoritmi relativ simpli, dar n general problema este dificil i analizm complexitatea algoritmilor n medie sau n cazul cel mai defavorabil. Complexitatea n cazul cel mai defavorabil este numrul maxim de operaii elementare efectuate de algoritm.
255

Dar chiar dac este cunoscut cazul cel mai defavorabil, datele utilizate efectiv n practic pot conduce la timpi de execuie mult mai mici. Numeroi algoritmi foarte utili au o comportare convenabil n practic, dar foarte proast n cazul cel mai defavorabil. Cel mai cunoscut exemplu este algoritmul de sortare rapid (quicksort) care are complexitatea n cazul cel mai defavorabil de O(n 2), dar pentru datele ntlnite n practic funcioneaz n O(n log n ). O alt modalitate de a studia performanele unui algoritm const n determinarea complexitii n medie. Pentru a determina complexitatea n medie este necesar cunoaterea repartiiei probabilistice a datelor de intrare i din acest motiv analiza complexitaii n medie este mai dificil de realizat. Pentru cazuri simple, de exemplu un algoritm de sortare care acioneaza asupra unui tablou cu n componente ntregi aleatoare sau un algoritm geometric pe o mulime de N puncte n plan de coordonate aleatoare cuprinse n intervalul [0,1], putem caracteriza exact datele de intrare. Dac notm : D-spaiul datelor de intrare p(d)-probabilitatea apariiei datei dD la intrarea algoritmului T A(d)-numrul de operaii elementare efectuate de algoritm pentru intrarea dD atunci complexitatea medie este p(d).TA(d).
d D

9.3. Exemple 9.3.1. Calcularea maximului Fiind date n elemente a 1, a2, ..., an, s se calculeze max {a1, a2, ..., an}. max := a[1]; for i := 2 to n do if a[i] > max then max := a[i];
256

Vom estima timpul de execuie al algoritmului n funcie de n, numrul de date de intrare. Fiecare iteraie a ciclului for o vom considera operaie elementar. Deci complexitatea algoritmului este O(n), att n medie ct i n cazul cel mai defavorabil. 9.3.2. Sortarea prin selecia maximului Fiind dat a, un vector cu n componente, s ordonm crector elementele vectorului. for dr := n downto 2 do begin max := a[1]; pozmax := 1; for i := 2 to dr do if a[i] > max then begin a[i] := max; pozmax := i end; a[pozmax] := a[dr]; a[dr] := max; end; Estimm complexitatea algoritmului n funcie de n, dimensiunea vectorului. La fiecare iteraie a ciclului for exterior este calculat max {a1, a2, ..., adr} i plasat pe poziia dr, elementele de la dr+1 la n fiind deja plasate pe poziiile lor definitive. Conform exemplului anterior, pentru a calcula max{a1, a2, ..., adr } sunt necesare dr-1 operaii elementare, n total 1+2+...+n-1 = n (n-1)/2. Deci complexitatea algoritmului este de O(n 2). S observm c timpul de execuie a algoritmului este independent de ordinea iniial a elementelor vectorului. 9.3.3. Sortarea prin inserie Este o metod de asemeni simpl, pe care o utilizm adesea cnd ordonm crile la jocuri de cri. for i := 2 to n do
257

begin val := a[i]; poz := i; while a[poz-1] > val do begin a[poz] := a[poz-1]; poz := poz-1; end; a[poz] := val end; Analizm algoritmul tot n funcie de n, dimensiunea vectorului a ce urmeaz a fi sortat. La fiecare iteraie a ciclului for elementele a 1, a2, ..., ai-1 sunt deja ordonate i trebuie s inserm valorea a [i] pe poziia corect n irul ordonat. n cazul cel mai defavorabil, cnd vectorul este iniial ordonat descresctor, fiecare element a [i] va fi plasat pe prima poziie, deci ciclul while se execut de i-1 ori. Considernd drept operaie elementar comparaia a[poz-1]>val urmat de deplasarea elementului de pe poziia poz-1, vom avea n cazul cel mai defavorabil 1+2+...+n-1 = n (n-1)/2 operaii elementare, deci complexitatea algoritmului este de O(n 2) . S analizm comportarea algoritmului n medie. Pentru aceasta, vom considera c elementele vectorului sunt distincte i c orice permutare a lor are aceeai probabilitate de apariie. Atunci probabilitatea ca valoarea ai s fie plasat pe poziia k n irul a 1, a2, ..., ai, k{1,2,....,i}este 1/i. Numrul mediu de operaii elementare, pentru i fixat este: i 1 1 i 1 i(i + 1) i +1 i 1 i) = 1= (k i ) = ( k i ) = ( i k=1 i 2 2 2 k=1 i Pentru a sorta cele n elemente sunt necesare n i 1 1 n(n + 1 ) 1 n(n + 1) n(n 1) = ( 1 (n 1)) = ( n) = 2 2 2 2 n i =2 2 operaii elementare. Deci complexitatea algoritmului n medie este tot O(n2). 9.3.4. Sortarea rapid (quicksort)
258

Elaborat de C.A.R. Hoare n 1960, este unul dintre cei mai utilizai algoritmi de sortare. procedure quicksort (st, dr : integer); var m: integer; begin //sorteaz vectorul a[st..dr] if st < dr then begin m := divide(st, dr); quicksort(st, m-1); quicksort(m+1, dr); end; Iniial apelm quicksort(1, n). function divide (st, dr: integer): integer; var i, j, val: integer; begin //plaseaz primul element (a [st]) pe poziia sa corect n irul ordonat. //n stnga sa se vor gsi numai elemente mai mici, n dreapta numai //elemente mai mari dect el val := a[st]; i := st; j := dr; while i < j do begin while (i < j) and (a[j] val) do j := j - 1 ; a[i] := a[j] ; while (i < j) and (a[i] val) do i := i + 1 ; a[j] := a[i] ; end ; a[i] := val ; divide := i ; end ; Observaie Vectorul a este considerat variabil global. n cazul cel mai defavorabil, cnd vectorul a era iniial ordonat, se fac n -1 apeluri succesive ale procedurii quicksort, cu parametrii (1,n), (1,n-1), ..., (1, 2) (dac vectorul a era iniial ordonat descresctor) sau (1,n), (2,n), ..., (n -1,n) (dac vectorul a era ordonat cresctor).
259

La fiecare apel al procedurii quicksort este apelat funcia divide(1,i) (respectiv divide(i , n) ) care efectueaz i -1, (respectiv n -i -1) operaii elementare. n total numrul de operaii elementare este n-1+n-2+... +1=n (n-1)/2. Complexitatea algoritmului n cazul cel mai defavorabil este de O(n2). S analizm comportarea algoritmului n medie. Considerm c orice permutare a elementelor vectorului are aceeai probabilitate de apariie i notm cu T n numrul de operaii elementare efectuate pentru a sorta n elemente. Probabilitatea ca un element al vectorului s fie plasat pe poziia k n vectorul ordonat, este de 1/n.

(pentru a ordona cresctor n elemente, determinm poziia k n vectorul ordonat a primului element, ceea ce necesit n-1 operaii elementare, sortm elementele din stnga, ceea ce necesit Tk-1 operaii elementare, apoi cele din dreapta, necesitnd T n-k operaii elementare). Problema se reduce la a rezolva relaia de recuren de mai sus. Mai nti observm c T 0+T1+ ... +Tn-1 = Tn-1+ ... +T1+T0. Deci, 2 n Tn = n 1+ Tk 1 n k=1 nmulim ambii membrii ai acestei relaii cu n. Obinem : n Tn = n(n 1) + 2 Tk 1 Scznd din aceast relaie, relaia obinut pentru n -1, adic (n 1) Tn 1 = (n 1)(n 2) + 2 Tk 1
k=1 n1 k=1 n

R |0, n T =S 1 (T | nk =1 T
n

dac n=0 sau n=1 ; +Tn k)+ n1 , dac n> 1

k1

obinem
260

n Tn (n 1) Tn 1 = n(n 1) (n 1)(n 2) + 2Tn 1 n Tn = 2(n 1) + (n + 1) Tn 1 mprind ambii membrii cu n.(n+1) obinem


n k 1 Tn Tn 1 2(n 1) Tn 2 2(n 1) 2(n 2) T2 = + = + + =... = +2 = n+ 1 n n(n + 1) n 1 n(n + 1) (n 1)n 3 ) k= 3 k(k + 1 n 1 T2 2 = + +2 3 n + 1 k=3 k Deci n 1 n 1 Tn 1 2 n1 = + + 2 2 2 1 dx = 2ln n n + 1 3 n + 1 k=3 k x k=1 k Am demonstrat astfel c, n medie, complexitatea algoritmului este de O(n log n).

9.3.5. Problema celebritii Numim celebritate o persoan care este cunoscut de toat lumea, dar nu cunoate pe nimeni. Se pune problema de a identifica o celebritate, dac exist, ntrun grup de n persoane pentru care relaiile dintre persoane sunt cunoscute. Observaie Putem reformula problema n limbaj de grafuri astfel : fiind dat un digraf cu n vrfuri, verificai dac exist un vrf cu gradul exterior 0 i gradul interior n-1. Reprezentm graful asociat problemei prin matricea de adiacen anxn 1 , dac persoana i cunoate pe j; ai , j = 0, altfel. O prim soluie ar fi s calculm pentru fiecare persoan p din grup numrul de persoane pe care p le cunoate (out) i numrul de persoane care cunosc persoana p (in). Cu alte cuvinte, pentru fiecare vrf din digraf calculm gradul interior i gradul exterior. Dac gsim o persoan pentru care out = 0 i in = n-1, aceasta va fi celebritatea cutat. celebritate := 0; for p := 1 to n do begin in := 0; out := 0;

261

for j := 1 to n do begin in := in+a[j,p]; out := out+a[p,j]; end; if (in = n-1) and (out = 0) then celebritate := p; end; if celebritate = 0 then writeln('n grup nu exist celebriti !') else writeln(p, ' este o celebritate.'); Se poate observa cu uurin c algoritmul este de O(n2). Putem mbunti algoritmul fcnd observaia c atunci cnd testm relaiile dintre persoanele x i y apar urmtoarele posibiliti : a[x,y] = 0 i n acest caz y nu are nici o ans s fie celebritate, sau a[x,y] = 1 i n acest caz x nu poate fi celebritate. Deci la un test eliminm o persoan care nu are anse s fie celebritate. Fcnd succesiv n-1 teste, n final vom avea o singur persoan candidat la celebritate. Rmne s calculm numrul de persoane cunoscute i numrul de persoane care l cunosc pe acest candidat, singura celebritate posibil. candidat := 1; for i := 2 to n do if a[candidat, i] = 1 then candidat := i; out := 0; in := 0; for i := 1 to n do begin in := in+a[i, candidat]; out := out+a[candidat, i] end; if (out = 0) and (in = n-1) then writeln(candidat, ' este o celebritate .') else
262

grup.'); n acest caz algoritmul a devenit liniar. 9.4. Exerciii

writeln('Nu exist celebriti n acest

1. Artai c : a) n3+106n2(n3) n n n b) n2 +6 2 (n2 ) c) 2 n2+n logn(n2) d) nk+n+nklogn(nk log n), k 1 e) logan(logbn), a, b > 0, a 1, b 1. 2. Demonstrai prin inducie c pentru a determina maximul a n numere sunt necesare n-1 comparaii. 3. Care este timpul de execuie a algoritmului quicksort pentru un vector cu n componente egale? 4. S considerm urmtorul algoritm de sortare a unui vector a cu n componente: repeat ok := true; for i := 1 to n-1 do if a[i] > a[i+1] then begin aux := a[i]; a[i] := a[i+1]; a[i+1] := aux; ok := false end until ok; Analizai algoritmul n medie i n cazul cel mai defavorabil. 5. Analizai complexitatea algoritmului de interclasare a doi vectori ordonai, a cu n componente, respectiv b cu m componente : i := 1; j := 1; k := 0; while (i n) and(j m) do begin k := k+1;
263

if a[i] < b[j] then begin c[k] := a[i]; i := i+1 end else begin c[k] := b[j]; j := j+1 end; end; for t := i to n do begin k := k+1; c[k] := a[t] end; for t := j to m do begin k := k+1; c[k] := b[t] end; 6. Fiind dat a, un vector cu n componente distincte, verificai dac o valoare dat x se gsete sau nu n vector. Evaluai complexitatea algoritmului n cazul cel mai defavorabil i n medie. 7. Problema turnurilor din Hanoi. Avem la dispoziie 3 tije numerotate 1, 2, 3 i n discuri de diametre diferite. Iniial, toate discurile sunt plasate pe tija 1 n ordinea descresctoare a diametrelor, considernd sensul de la baz la vrf. Problema const n a muta discurile de pe tija 1 pe tija 2, folosind ca tij de manevr, tija 3, respectnd urmtoarele reguli : - la fiecare pas se mut un singur disc; - orice disc nu poate fi aezat dect peste un disc cu diametru mai mare. Aceast problem a fost propus la sfritul secolului trecut de ctre matematicianul francez Eduard Lucas, care a comercializat-o sub forma unui joc cu 8
264

discuri i 3 baghete numit "Turnul din Hanoi". Jocul este inspirat dintr-o strveche legend hindus, dup care zeul Brahma ar fi fixat pe o mas a templului su din Benares 3 baghete verticale de diamant, pe una din ele plasnd 64 de discuri de aur n ordinea descresctoare a diametrelor. Zi i noapte clugrii templului mutau discuri de pe tija 1 pe tija 2, folosind ca tij de manevr tija 3, respectnd ordinea descresctoare a diametrelor. Legenda spune c atunci cnd toate discurile vor fi mutate va fi sfritul lumii. Scriei un algoritm de rezolvare a problemei turnurilor din Hanoi i estimai complexitatea acestuia. Estimai, n particular, durata legendar a vieii pe Pmnt. 8. Se d a un vector cu n componente. Scriei un algoritm liniar care s determine cea mai lung secven de elemente consecutive de valori egale. 9. Fie T un text. Verificai n timp liniar dac un text dat T este o permutare circular a lui T. 10. Fie X = x1, x2, ..., xn o secven de numere ntregi. Fiind dat x, vom numi multiplicitate a lui x n X numrul de apariii ale lui x n X. Un element se numete majoritar dac multiplicitatea sa este mai mare dect n/2. Descriei un algoritm liniar care s determine elementul majoritar dintr-un ir, dac un astfel de element exist. 11. Fie {a1, a2, ..., an } i {b1, b2, ..., bm}, dou mulimi de numere ntregi, nenule (m < n). S se determine {x1, x2, ..., xm}, o submulime a mulimii {a1, a2, ..., an} pentru care funcia f(x1, x2, ..., xm) = a1x1+a2x2+...+anxm ia valoare maxim, prin doi algoritmi de complexitate diferit.

265