===== Soluții notații asimptotice și analiză amortizată =====
==== Notații asimptotice ====
1. Dați exemple de câte o funcție din următoarele clase de complexitate:
$ O(n)$
Trebuie sa gasim functii care cresc maxim la fel de repede ca f(n)=n.
Exemple soluții posibile: g(n)=n+6, g(n)=8n+7 (aceeasi crestere),
g(n)=log(n) (crestere mai mica)
$Ω(log(n))$
Trebuie sa gasim functii care cresc mai repede sau la fel de repede ca f(n)=n^2.
Exemple soluții posibile: g(n)=100*log(n)+5, (aceeasi crestere), g(n)=n^3,
g(n)=nlog(n) (mai repede)
$θ(n^2)$
Trebuie sa gasim functii care cresc la fel de repede ca f(n)=log(n).
Exemple soluții posibile: g(n)=a*n^2+b*n+c*log(n)+d, a>0 (aceeasi crestere ca n^2, fiind dominant in functie)
$ɷ(1/n)$
Trebuie sa gasim functii care cresc strict mai repede decat f(n)=1/n.
Cum 1/n este o functie descrescatoare, solutia este orice functie crescatoare.
Exemple soluții posibile: g(n)=c, c = constanta, g(n)=n+23, g(n)=nlogn+n^4 etc.
$ o(3^n)$
Trebuie sa gasim functii care cresc strict mai incet decat f(n)=3^n.
Exemple soluții posibile: g(n)=n^p,p>=0 etc.
2. Verificați valoarea de adevăr a următoarelor propoziții:
$ √n∈O(logn)$
f(n)=logn, g(n)=√n. Cum f si g sunt functiile f si g sunt monotone si cresctoare, verific afirmatia utilizand limite.
lim(n→∞)(g(n)/f(n))=lim(n→∞)(√n/log(n))=(l'Hospital)lim(n→∞)(n/2*√n)=1/2*lim(n→∞)(√n)=+∞ => **Fals**
$ logn∈O(log(log n))$
f(n)=log(logn), g(n)=logn. Cum f si g sunt functiile f si g sunt monotone si cresctoare, verific afirmatia utilizand limite.
lim(n→∞)(g(n)/f(n))=lim(n→∞)(logn/log(log n))=(l'Hospital)lim(n→∞)(1/n / 1/logn * 1/n)=1/2*lim(n→∞)(logn)=+∞ => **Fals**
$ n∈O(√n logn)$
f(n)=√n logn, g(n)=n. Cum f si g sunt functiile f si g sunt monotone si cresctoare, verific afirmatia utilizand limite.
lim(n→∞)(g(n)/f(n))=lim(n→∞)(n/√n logn)=lim(n→∞)(√n/logn)=(l'Hospital)lim(n→∞)(1/2 * 1/n^2 / 1/n)=1/2*lim(n→∞)(1/n)=0 => **Fals**
$ n+logn∈θ(n)$
f(n)=n, g(n)=n + logn. Cum f si g sunt functiile f si g sunt monotone si cresctoare, verific afirmatia utilizand limite.
lim(n→∞)(g(n)/f(n))=lim(n→∞)(n + logn/n)=1 + lim(n→∞)(logn/n)=(l'Hospital)1 + lim(n→∞)(1/n)= 1 => **Adevarat**
$ log(nlogn)∈θ(logn)$
f(n)=logn, g(n)=log(nlogn). Cum f si g sunt functiile f si g sunt monotone si cresctoare, verific afirmatia utilizand limite.
lim(n→∞)(g(n)/f(n))==(l'Hospital)lim(n→∞)(1/nlogn*(logn+1) / 1/n)=lim(n→∞)(1/logn*(logn+1)) =lim(n→∞)(1 + 1/logn)=1 => **Adevarat**
$ √n∈ɷ(log n)$
f(n)=logn, g(n)= √n. Cum f si g sunt functiile f si g sunt monotone si cresctoare, verific afirmatia utilizand limite.
lim(n→∞)(g(n)/f(n))=lim(n→∞)(√n/logn)= (l'Hospital)lim(n→∞)(1/2*√n)= ∞ => **Adevarat**
==== Analiză amortizată ====
1.
#include
#include
#include
#define COUNTER_SIZE 100
unsigned total_flips = 0;
int inc(unsigned *a, size_t m)
{
size_t i = 0;
unsigned current_flips = 0;
while (i < m && a[i] == 1) {
a[i] = 0;
current_flips++;
i++;
}
if (i == m) {
total_flips += current_flips;
return -1;
}
a[i] = 1;
current_flips++;
total_flips += current_flips;
return 0;
}
int main(int argc, char *argv[])
{
unsigned counter[COUNTER_SIZE];
memset(counter, 0, sizeof(counter));
if (argc < 2) {
fprintf(stderr, "Usage: %s \n", argv[0]);
return 1;
}
unsigned n = strtoull(argv[1], NULL, 10);
if (n == 0) {
fprintf(stderr, "Invalid number of increments: %s\n", argv[1]);
return 1;
}
for (int i = 0; i < n; i++) {
inc(counter, COUNTER_SIZE);
}
printf("Total flips: %u\n", total_flips);
}