Sunteți pe pagina 1din 7

FMI- Curs Greedy verman@fmi.unibuc.

ro

Metoda Divide et Impera


Metoda Divide et Impera ("desparte i stpnete") const n mprirea repetat a unei
probleme de dimensiuni mari n mai multe subprobleme de acelai tip, urmat de rezolvarea
acestora i combinarea rezultatelor obinute pentru a determina rezultatul corespunztor
problemei iniiale. Pentru fiecare subproblem procedm n acelai mod, cu excepia cazului n
care dimensiunea ei este suficient de mic pentru a fi rezolvat direct.
Este evident caracterul
recursiv al acestei metode.

Schema general
function DivImp(p,u)
if up<
r Rezolva(p,u)
else m Interm(p,u);
r1 DivImp(p,m);
r2 DivImp(m+1,u);
r Combina(r1,r2)
return r
end;

Exemple:

Calculul celui mai mare divizor comun al elementelor unui vector a;

function DivImp(p,u)
if up<2
r Cmmdc2(a[p],a[u])
else m (p+u)/2;
r1 DivImp(p,m);
r2 DivImp(m+1,u);
r Cmmdc2(r1,r2)
return r
end;

unde funcia Cmmdc2(a,b) calculeaz cel mai mare divizor comun a dou numere a i b
Parcurgerile n preordine, inordine i postordine ale unui arbore binar;
Sortarea folosind arbori de sortare.
Mai pe scurt, putem spune:
Metoda Divide et Impera const n:
- construirea dinamic a unui arbore (prin mprirea n subprobleme) urmat de
- parcurgerea n postordine a arborelui (prin asamblarea rezultatelor pariale).

Cutarea binar (de tiut, nediscutat la curs)


Se consider vectorul a=(a1,...,an) ordonat cresctor i o valoare x. Se cere s se
determine dac x apare printre componentele vectorului.
Mai exact cutm perechea (b,i) dat de:
(true,i)
dac ai = x;
(false,i)
dac ai-1<x<ai,
unde a0 = -, an+1= +.
Problema enunat constituie un exemplu pentru cazul n care problema se reduce la o
singur subproblem.
innd cont de faptul c a este ordonat cresctor, vom compara pe x cu elementul din
"mijlocul" vectorului. Dac avem egalitate, algoritmul se ncheie; n caz contrar vom cuta fie n
"jumtatea" din stnga, fie n cea din dreapta.
Deoarece problema se reduce la o singur subproblem, nu mai este necesar s folosim
recursivitatea.
Algoritmul este urmtorul:
procedure CautBin
p 1; u n
while pu
i (p+u)/2
{pentru a evita depasiri este de preferat i p+(u-p)/2
case ai>x : u i-1
ai=x : write(true,i); stop
ai<x : p i+1
write(false,p)
end

Algoritmul necesit o mic analiz, legat de corectitudinea sa parial. Mai precis, ne


ntrebm: cnd se ajunge la p>u?

pentru cel puin 3 elemente : nu se poate ajunge la p>u;

pentru 2 elemente, adic pentru u=p+1: se alege i=p. Dac x<ai, atunci up-1. Se observ
c se iese din ciclul while i ai-1<x<ai=ap;

pentru un element, adic p=u: se alege i=p=u. Dac x<ai atunci up-1, iar dac x>ai
atunci pu+1; n ambele cazuri se prsete ciclul while i tiprete un rezultat corect.

Complexitate. Presupunem c n=2k. Atunci avem


T(n) = T(n/2)+c = = T(n/2k)+kc

Rezult T(n) = O(log n)

Sortare prin interclasare (de tiut, nediscutat la curs)


Fie a=(a1,...,an) vectorul care trebuie ordonat cresctor.
Ideea este urmtoarea: mprim vectorul n doi subvectori, ordonm cresctor fiecare
subvector i asamblm rezultatele prin interclasare. Se observ c este aplicat tocmai metoda
Divide et Impera.
Programul principal urmeaz ntocmai strategia Divide et Impera, deci se face apelul
SortInter(1,n), unde procedura recursiv SortInter are forma:
procedure SortInter(p,u)
if p = u
else m (p+u)/2;
SortInter(p,m);
SortInter(m+1,u);
Inter(p,m,u)
end

Presupunnd c (ap,...,am) i (am+1,...,au) sunt ordonai cresctor, procedura de


interclasare Inter va ordona cresctor ntreaga secven (ap,...,au) (pentru implementare,
vezi aplicaia urmtoare). Timpul de calcul al procedurii este de ordinul O(u-p), adic liniar n
lungimea secvenei analizate.
Complexitate. Calculm n continuare timpul de executare al sortrii prin interclasare T(n),
unde T(n) se poate scrie:

t0 (constant), pentru n=1;

2T(n/2)+an, pentru n>1, unde a este o constant: problema de dimensiune n s-a descompus

n dou subprobleme de dimensiune n/2, iar combinarea rezultatelor s-a fcut n timp liniar
(prin interclasare).
Presupunem c n=2k. Atunci:
T(n) = T(2k) = 2 T(2k-1) + a 2k =
= 2[2T(2k-2) + a 2k-1] + a 2k = 22T(2k-2) + 2 a 2k =
= 22[T(2k-3) + a 2k-2] + 2 a 2k = 23T(2k-3) + 3 a 2k =
. . .
= 2iT(2k-i) + i a 2k =
. . .
= 2kT(1) + k a 2k = nt0 + a. n .log2n.

Rezult c T(n)=0(n.log n).


Meniune. Se poate demonstra c acest timp este optim, folosind arbori de decizie.

Numrul de inversiuni
Problem (aplicaie). Se consider un vector cu n elemente. S de determine numrul de
inversiuni din acest vector (numrul de perechi (i, j) cu proprietatea c i < j i ai > aj)
Aplicaii:
Msur a diferenei ntre dou liste ordonate
Gradul de ordonare al unui vector
Probleme de analiz a clasificrilor (ranking)
Asemnarea ntre preferinele a doi utilizatori sugestii de utilizatori cu preferine
similare
Asemnri dintre rezultatele ntoarse de motoare diferite de cutare pentru aceeai
cerere
collaborative filtering
Soluie. Un algoritm cu complexitatea O(n2) este evident. Putem ns rezolva problema printr-un
algoritm cu complexitatea O(n lg n), numrnd inversiunile n timpul sortrii prin interclasare.
Mai exact:
numrul de inversiuni dintr-un vector = numrul de inversiuni din subvectorul stng (prima
jumtate) + numrul de inversiuni din subvectorul drept + numrul de inversiuni (i, j) cu i m
indice n subvectorul stng i j > m indice n subvectorul drept (am notat cu m indicele
elementului din mijlocul vectorului).
Pentru a numra inversiunile (i, j) cu i m i j > m observm c la interclasare au loc
urmtoarele:
1. cnd un element de pe poziia j cu j > m este adugat n vectorul rezultat, el este mai mic
(doar) dect toate elementele din subvectorul stng neadugate nc n vectorul rezultat;
astfel, a[j] determin m i + 1 inversiuni cu elemente din subvectorul stng
2. cnd un element de pe poziia i cu i m este adugat n vectorul rezultat, el este mai
mare (doar) dect toate elementele din subvectorul drept adugate deja la vectorul rezultat
Avem astfel dou modaliti de a numra inversiunile la interclasare.
Implementarea acestei aplicaii se gsete n fiierul Inversiuni_1.java (varianta 1) i
Inversiuni_2.java (varianta 2)
Exemplu - vezi slideuri curs DI

Metoda Quicksort (de tiut, nediscutat la curs)


Prezentm nc o metod de sortare a unui vector a=(a1,...,an). Va fi aplicat tot
metoda Divide et Impera. i de aceast dat fiecare problem va fi descompus n dou
subprobleme mai mici de aceeai natur, dar nu va mai fi necesar combinarea (asamblarea)
rezultatelor rezolvrii subproblemelor.
4

5
Fie (ap,...,au) secvena curent care trebuie sortat. Vom poziiona pe ap n secvena
(ap,...,au), adic printr-o permutare a elementelor secvenei:
x=ap va trece pe o poziie k;
toate elementele aflate la stnga poziiei k vor fi mai mici dect x;
toate elementele aflate la dreapta poziiei k vor fi mai mari dect x.
n acest mod ap va aprea pe poziia sa final, rmnnd apoi s ordonm cresctor
elementele aflate la stnga sa, precum i pe cele aflate la dreapta sa.
Fie poz funcia cu parametrii p,u care ntoarce indicele k pe care va fi poziionat ap n
cadrul secvenei (ap,...,au).
Atunci sortarea se realizeaz prin apelul QuickSort(1,n), unde procedura QuickSort
are forma:
procedure QuickSort(p,u)
if p = u
else m poz(p,u); QuickSort(p,m-1); QuickSort(m+1,n)
end

Funcia poz lucreaz astfel:


function poz(p,u)
ip; ju; di0; dj-1
while i<j
if ai>aj
aiaj; (di,dj)(-dj,-di)

(*)

ii+di; jj+dj
return i
end
unde prin am notat interschimbarea valorilor.

S urmrim cum decurg calculele pentru secvena:


(a4,...,a11)=(6,3,2,5,8,1,9,7)

se compar 6 cu a11,a10,... pn cnd gsim un element mai mic. Acesta este a9 = 1. Se


interschimb 6 cu 1. Acum secvena este (1,3,2,5,8,6,9,7) i vom lucra n continuare
pe subsecvena (3,2,5,8,6), schimbnd direcia de comparare conform (*);
6 va fi comparat succesiv cu 3,2,... pn cnd gsim un element mai mare. Acesta este
a8=8. Se interschimb 6 cu 8.
Se obine astfel (1,3,2,5,6,8,9,7), n care la stnga lui 6 apar valori mai mici, iar la
dreapta lui 6 apar valori mai mari, deci l-am poziionat pe 6 pe poziia 8, valoare ntoars de
funcia poz.
Complexitate.
Cazul cel mai defavorabil pentru metoda Quicksort este cel n care vectorul este deja
ordonat cresctor: se compar a1 cu a2,...,an rezultnd c el se afl pe poziia final, apoi se
compar a2 cu a3,...,an rezultnd c el se afl pe poziia final etc.
5

6
Trecem la calculul timpului mediu de executare al algoritmului Quicksort. Vom numra
cte comparri se efectueaz (componentele vectorului nu sunt neaprat numere, ci elemente
dintr-o mulime ordonat oarecare). Timpul mediu este dat de formulele:

1
T(n) n 1
n

T(1) T 0 0

[T(k 1) T(n k)]

k 1

deoarece:
n cazul cel mai defavorabil a1 se compar cu celelalte n-1 elemente;
a1 poate fi poziionat pe oricare dintre poziiile k=1,2,...,n; considerm aceste cazuri
echiprobabile;
T(k-1) este timpul (numrul de comparri) necesar ordonrii elementelor aflate la stnga
poziiei k, iar T(n-k) este timpul necesar ordonrii elementelor aflate la dreapta poziiei k.
nT(n) = n(n-1)+2[T(0)+T(1)+...+T(n-1)]
(n-1)T(n-1) = (n-1)(n-2)+2[T(0)+...+T(n-2)]

Scznd cele dou relaii obinem:


nT(n)(n-1)T(n-1) = 2(n-1)+ 2T(n-1), deci:
nT(n) = (n+1)T(n-1)+2(n-1).

mprim cu n(n+1):
T(n) T(n 1) 2(n 1)

n 1
n
n(n 1)
T(n) T(n 1) 2
1

2

n 1
n
n

1
n

T(n 1) T(n 2) 2
1

n
n 1
n n 1
...........................
T(2) T(1) 2 1

2
3
2
3 2

Prin adunarea relaiilor de mai sus obinem:


1
1
2
1
.....
1

1
n
3
n
1

T(n)
2
n 1

n+1

Cum suma ultimilor doi termeni este negativ, rezult:


n 1

T(n)
2
n 1

1
dx 2lnx|2n 1 2.ln(n+1)
x

(am folosit o inegalitate bazat pe sumele Riemann inferioare pentru funcia f(x)=1/ x).
Deci T(n)=O(n.log n).
Variant (cu rezultate bune n practic): Sortarea prin interclasare cu pivot aleator
procedure QuickSortR(p,u)
if p = u
else k pozRand(p,u); QuickSortR(p,k-1); QuickSortR(k+1,n)
end

Funcia pozRand lucreaz astfel:


6

7
function pozRand(p,u)
r random(p,u);
end

a[r] a[p];

return poz(p,u)

Statistici de ordine
Problem (aplicaie). Dat un vector a de n numere i un indice k, 1 k n, s se determine
al k-lea cel mai mic element din vector.
Soluie. Cadru general: Statistici de ordine
A i-a statistic de ordine a unei mulimi de n elemente este al i-lea cel mai mic element.
Minimul = prima statistic de ordine
Maximul = a n-a statistic de ordine
Mediana = punctul de la jumtatea drumului unei mulimi = o valoare v cu proprietatea
c numrul de elemente din mulime mai mici dect v este egal cu numrul de elemente
din mulime mai mari dect v. Dac n este impar, atunci mediana este a n/2 -a statistic
de ordine, altfel, prin convenie mediana este media aritmetic dintre a n/2 -a statistic
i a ( n/2 +1)-a statistic de ordine
Un algoritm optim de determinare a minimului sau maximului necesit n 1 comparaii, iar un
algoritm de determinare simultan a minimului i maximului, 3 n/2 -2 comparaii (v. seminar).
Pentru a rezolva problema determinrii celui de al k-ale minim (celei de a k-a statistic de ordine)
folosim idea de partiionare de la QuickSort
function kmin(p,u)
m pozRand(p,u);
if (m = k)
return am
if(m < k) return kmin(m+1,u)
else
return kmin(p,m-1)
end

Exemplu - vezi slideuri curs DI


O implementare a acestui algoritm se gsete n fiierul AlKMinim.java
Observaii. 1. Timpul mediu de executare al acestui algoritm este O(n). Mai exact se poate
demonstra prin inducie c pentru o constant c suficient de mare avem T(n) cn (consultai
cursul scris + Cormen pentru mai multe detalii)
2. Exist algoritm cu complexitate O(n) pentru determinarea celei de a i-a statistic de ordine.
Tem (Referat +1p) - studiu comparativ al algoritmilor de determinare a celei de a i-a statistici
de ordine (descrierea algoritmilor, exemplu, corectitudine, discuii complexitate timp i spaiu,
implementare, comparare timpi de rulare pe date mari etc)
Tem - Problema elementului majoritar Se d un ir de n numere naturale. Se cere
determinarea unui element care apare de cel puin [n/2]+1 ori n ir, dac exist. Acest element
se numete element majoritar (http://infoarena.ro/problema-majoritatii-votului)
7

S-ar putea să vă placă și