Algoritmi e Strutture Dati Notes

Algoritmi, Efficienza e RAM

Algoritmi e Strutture Dati

  • L'informatica è definita come la scienza degli algoritmi che descrivono e trasformano l'informazione.

  • Un algoritmo è una sequenza di comandi elementari e univoci che terminano in un tempo finito e operano su strutture dati.

  • I comandi elementari non possono essere ulteriormente scomposti e sono univoci.

  • Un algoritmo ben specificato non richiede che l'esecutore pensi, ma solo che esegua i passi precisamente.

  • Se un calcolatore produce un output errato, è colpa del progettista dell'algoritmo, non del calcolatore.

  • Le strutture dati sono necessarie per gestire i dati utilizzati dall'algoritmo, organizzandoli e memorizzandoli per semplificare l'accesso e la modifica.

Efficienza di un algoritmo

  • Non esiste una struttura dati adatta a ogni problema; è necessario conoscere i vantaggi e gli svantaggi delle principali strutture dati.

  • La scelta della struttura dati è fondamentale quanto la progettazione dell'algoritmo.

  • L'efficienza di un algoritmo si misura in termini di tempo di esecuzione e quantità di memoria richiesta.

  • I calcolatori sono veloci ma non infinitamente.

  • La memoria è economica ma non gratuita né illimitata.

  • Il costo computazionale degli algoritmi è valutato in termini di numero di operazioni elementari e quantità di memoria necessaria in funzione della dimensione dell'input.

  • Esempio: Ordinamento di n=106n = 10^6 numeri interi.

    • Calcolatore V: 10910^9 operazioni/sec

    • Calcolatore L: 10710^7 operazioni/sec

    • Algoritmo Insertion Sort (IS): 2n22n^2 operazioni

    • Algoritmo Merge Sort (MS): 50nlog2(n)50n \cdot log_2(n) operazioni

    • Costo temporale:

      • V(IS)=(2(106)2)/(109)=2000 sec33 minV(IS) = (2 \cdot (10^6)^2) / (10^9) = 2000 \text{ sec} \approx 33 \text{ min}

      • L(MS)=(50106log2(106))/(107)100 sec1.5 minL(MS) = (50 \cdot 10^6 \cdot log_2(10^6)) / (10^7) \approx 100 \text{ sec} \approx 1.5 \text{ min}

  • Aumentando l'input a n=107n = 10^7:

    • V(IS)55.5V(IS) \approx 55.5 ore 2.3\approx 2.3 giorni

    • L(MS)19.5L(MS) \approx 19.5 min

Random Access Machine (RAM)
  • Per valutare l'efficienza di un algoritmo, è necessario quantificare le risorse richieste senza essere influenzati dalla tecnologia specifica.

  • La Random Access Machine (RAM) è una macchina astratta con le seguenti caratteristiche:

    • Singolo processore che esegue le operazioni sequenzialmente.

    • Operazioni elementari con tempo di esecuzione costante.

    • Limite alla dimensione di ogni valore memorizzato.

Misura di Costo Uniforme
  • Sia dd la dimensione di bit di ogni parola in memoria.

  • Se ogni dato in input è minore di 2d2^d, ogni operazione elementare sui dati viene eseguita in tempo costante (misura di costo uniforme).

  • Se un dato non rispetta tale ipotesi, sono necessarie più parole di memoria, e le operazioni richiedono un tempo non costante.

  • In ambito scientifico si utilizza la misura di costo logaritmica, ma in questo corso non verrà analizzata.

  • Esempio:

    • Codice:
      def PotenzaDi2(n): x = 1 for i in range(n): x = x*2 return x

    • Il tempo di esecuzione è proporzionale a nn, poiché il ciclo viene eseguito nn volte, con tre operazioni di costo unitario ad ogni iterazione.

Notazione Asintotica

Notazione O grande, Omega e Teta

  • La notazione asintotica permette di valutare l'efficienza di un algoritmo confrontandone il costo computazionale con altri algoritmi.

  • Ci si limita a valutare il tasso di crescita, cioè la velocità con cui il tempo di esecuzione cresce all'aumentare della dimensione dell'input.

  • La valutazione è efficace quando la dimensione dell'input è sufficientemente grande.

  • La notazione asintotica confronta il tasso di crescita di una funzione rispetto a un'altra.

  • Esistono tre tipologie principali di notazione asintotica:

    • O grande: limite superiore asintotico.

    • Ω\Omega (Omega): limite inferiore asintotico.

    • Θ\Theta (Teta): limite asintotico stretto.

Notazione O grande
  • Definizione: Date due funzioni f(n),g(n)0f(n), g(n) \geq 0, f(n)f(n) è in O(g(n))O(g(n)) se esistono due costanti cc ed n<em>0n<em>0 tali che 0f(n)cg(n)0 \leq f(n) \leq c \cdot g(n) per ogni nn</em>0n \geq n</em>0.

  • O(g(n))O(g(n)) contiene tutte le funzioni "dominate" da g(n)g(n).

  • La notazione O grande definisce il limite superiore asintotico di f(n)f(n):

    • Oltre un certo valore n0n_0, f(n)f(n) è limitata da cg(n)c \cdot g(n).

  • Esempi:

    • f(n)=3n+3f(n) = 3n + 3 è in O(n2)O(n^2), con c=6c = 6 e n0=1n_0 = 1

    • f(n)=3n+3f(n) = 3n + 3 è in O(n)O(n), con c6c \geq 6 e n0=1n_0 = 1

    • f(n)=n2+4nf(n) = n^2 + 4n è in O(n2)O(n^2), con c5c \geq 5 e n0=1n_0 = 1

  • Teorema: Sia f(n)=<em>i=0ma</em>ini=a<em>0+a</em>1n+a<em>2n2++a</em>mnmf(n) = \sum<em>{i=0}^{m} a</em>i n^i = a<em>0 + a</em>1 n + a<em>2 n^2 + … + a</em>m n^m un polinomio di grado mm, allora f(n)f(n) è in O(nm)O(n^m). Dimostrazione per induzione:

    • Caso base: m=0m=0, per cui f(n)=a0n0f(n)= a_0 \cdot n^0, dunque è una funzione costante e di conseguenza è in O(1)O(1), che coincide con O(n0)O(n^0)

    • Ipotesi induttiva: --> Affermiamo che <em>i=0ka</em>ini\sum<em>{i=0}^{k} a</em>in^i è un O(nk)O(n^k) per ogni k < m, cioè esiste una costante c' tale che <em>i=0ka</em>inicnk\sum<em>{i=0}^{k} a</em>in^i \leq c'\cdot n^k

    • Passo induttivo: --> Dobbiamo dimostrare che f(n)=<em>i=0ma</em>inicnmf(n)=\sum<em>{i=0}^{m} a</em>in^i \leq c''\cdot n^m
      Si osservi che, mettendo in evidenza l'ipotesi induttiva, f(n) può essere riscritto come
      f(n)=<em>i=0ma</em>ini=a<em>mnm+</em>i=0ka<em>inif(n) = \sum<em>{i=0}^{m} a</em>in^i = a<em>mn^m + \sum</em>{i=0}^{k} a<em>in^i per ogni ki=0kainicnkk{i=0}^{k} ain^i \leq c'\cdot n^k dunque possiamo formulare la seguente catena di disuguaglianze f(n)=amnm+i=0kainiamnm+cnkamnm+cnmf(n) = amn^m + \sum{i=0}^{k} ain^i \leq amn^m + c'\cdot n^k \leq amn^m + c'\cdot n^m
      ricrivendo amnm+cnmamn^m + c'\cdot n^m come (am+c)nm(am + c')\cdot n^me ponendo c=am+cc'' = a_m + c' otteniamo che f(n)cnmf(n) \leq c''\cdot n^m
      che per ipotesi sappiamo essere vera, dunque concludiamo che f(n)f(n), è in O(nm)O(n^m)

Notazione Omega
  • Definizione: Date due funzioni f(n),g(n)0f(n), g(n) \geq 0, f(n)f(n) è in Ω(g(n))\Omega(g(n)) se esistono due costanti cc ed n0n0 tali che f(n)cg(n)f(n) \geq c \cdot g(n) per ogni nn0n \geq n0.

  • Ω(g(n))\Omega(g(n)) contiene tutte le funzioni che "dominano" la funzione g(n)g(n).

  • La notazione Omega definisce il limite inferiore asintotico di f(n)f(n):

    • Oltre un certo valore n0n_0, f(n)f(n) è limitata inferiormente da cg(n)c \cdot g(n).

  • Esempi:

    • f(n)=2n2+3f(n) = 2n^2 + 3 è in Ω(n)\Omega(n), con c=1c = 1

    • f(n)=2n2+3f(n) = 2n^2 + 3 è in Ω(n2)\Omega(n^2), con c2c \leq 2

  • Teorema: Sia f(n)=i=0maini=a0+a1n+a2n2++amnmf(n) = \sum{i=0}^{m} ai n^i = a0 + a1 n + a2 n^2 + … + am n^m un polinomio di grado mm, allora f(n)f(n) è in Ω(nm)\Omega(n^m).

  • La dimostrazione è analoga alla dimostrazione del teorema per la notazione O grande.

Ordini di grandezza di O grande ed Omega
  • f(n)=log(n)f(n) = log(n) è in O(n)O(\sqrt{n}) e in Ω(1)\Omega(1).

    • loga(n)=O(nb)log_a(n) = O(\sqrt[b]{n}) per ogni a,b1a, b \geq 1

    • na=Ω(1)n^a = \Omega(1) per ogni aa

    • Un poli-logaritmo è dominato da qualunque radice e domina qualunque costante.

  • f(n)=naf(n) = \sqrt[a]{n} è in O(n)O(n) e in Ω(log(n))\Omega(log(n)).

    • na=O(nb)\sqrt[a]{n} = O(n^b) per ogni a,b1a, b \geq 1

    • na=Ω(logb(n))\sqrt[a]{n} = \Omega(log_b(n)) per ogni a,b1a, b \geq 1

    • Una radice è dominata da qualunque polinomio e domina qualunque poli-logaritmo.

  • f(n)=naf(n) = n^a è in O(2n)O(2^n) e in Ω(nb)\Omega(\sqrt[b]{n}).

    • na=O(bn)n^a = O(b^n) per ogni a1a \geq 1 ed ogni b2b \geq 2

    • na=Ω(nb)n^a = \Omega(\sqrt[b]{n}) per ogni a,b1a, b \geq 1

    • Un polinomio è dominato da qualunque esponenziale e domina qualunque radice.

  • Scala degli ordini di grandezza (per n+n \rightarrow +\infty):
    1loga(n)nbncdnn!nn1 \prec log_a(n) \prec \sqrt[b]{n} \prec n^c \prec d^n \prec n! \prec n^n

Notazione Teta
  • Definizione: Date due funzioni f(n),g(n)0f(n), g(n) \geq 0, f(n)f(n) è in Θ(g(n))\Theta(g(n)) se esistono tre costanti c1,c2c1, c2 ed n0n0 tali che c1g(n)f(n)c2g(n)c1 \cdot g(n) \leq f(n) \leq c2 \cdot g(n) per ogni nn0n \geq n0.

  • Se f(n)f(n) è sia in O(g(n))O(g(n)) sia in Ω(g(n))\Omega(g(n)), allora è anche in Θ(g(n))\Theta(g(n)).

  • La notazione Teta rappresenta il limite stretto asintotico della funzione.

Calcolo delle Notazioni Asintotiche con i Limiti
  • \lim_{n\to+\infty} \frac{f(n)}{g(n)} = k > 0 \Rightarrow f(n) = \Theta(g(n))

  • limn+f(n)g(n)=+f(n)=Ω(g(n)) ma f(n)Θ(g(n))\lim_{n\to+\infty} \frac{f(n)}{g(n)} = +\infty \Rightarrow f(n) = \Omega(g(n)) \text{ ma } f(n) \neq \Theta(g(n))

  • limn+f(n)g(n)=0f(n)=O(g(n)) ma f(n)Θ(g(n))\lim_{n\to+\infty} \frac{f(n)}{g(n)} = 0 \Rightarrow f(n) = O(g(n)) \text{ ma } f(n) \neq \Theta(g(n))

  • Se il limite del rapporto tra f(n)f(n) e g(n)g(n) non esiste, allora è necessario procedere diversamente.

Algebra della Notazione Asintotica

  • Per semplificare il calcolo del costo computazionale tramite limite asintotico degli algoritmi, si possono utilizzare tre regole algebriche:

    • Regola delle costanti moltiplicative.

    • Regola della commutatività con somma.

    • Regola della commutatività con prodotto.

Regola delle Costanti Moltiplicative
  • Per ogni k > 0 e per ogni f(n)0f(n) \geq 0, se f(n)f(n) è in O(g(n))O(g(n)), allora anche kf(n)k \cdot f(n) è in O(g(n))O(g(n)).

  • Per ogni k > 0 e per ogni f(n)0f(n) \geq 0, se f(n)f(n) è in Ω(g(n))\Omega(g(n)), allora anche kf(n)k \cdot f(n) è in Ω(g(n))\Omega(g(n)).

  • Per ogni k > 0 e per ogni f(n)0f(n) \geq 0, se f(n)f(n) è in Θ(g(n))\Theta(g(n)), allora anche kf(n)k \cdot f(n) è in Θ(g(n))\Theta(g(n)).

  • Le costanti moltiplicative possono essere ignorate durante il calcolo di un qualsiasi limite asintotico.

  • Attenzione: La costante moltiplicativa non deve essere all'esponente della funzione (es: in f(n)=2knf(n)=2^{k \cdot n} non possiamo ignorare la kk).

Regola della Commutatività con Somma
  • Sia f(n)=p(n)+q(n)f(n) = p(n) + q(n). Per ogni p(n), q(n) > 0, vale che:

    • Se p(n)p(n) è in O(g(n))O(g(n)) e q(n)q(n) è in O(h(n))O(h(n)), allora f(n)f(n) è in O(g(n)+h(n))=O(max(g(n),h(n)))O(g(n) + h(n)) = O(max(g(n), h(n))).

    • Se p(n)p(n) è in Ω(g(n))\Omega(g(n)) e q(n)q(n) è in Ω(h(n))\Omega(h(n)), allora f(n)f(n) è in Ω(g(n)+h(n))=Ω(max(g(n),h(n)))\Omega(g(n) + h(n)) = \Omega(max(g(n), h(n))).

    • Se p(n)p(n) è in Θ(g(n))\Theta(g(n)) e q(n)q(n) è in Θ(h(n))\Theta(h(n)), allora f(n)f(n) è in Θ(g(n)+h(n))=Θ(max(g(n),h(n)))\Theta(g(n) + h(n)) = \Theta(max(g(n), h(n))).

  • Un qualsiasi limite asintotico di f(n)f(n) è uguale al massimo tra il limite asintotico di p(n)p(n) e di q(n)q(n).

Regola della Commutatività con Prodotto
  • Sia f(n)=p(n)q(n)f(n) = p(n) \cdot q(n). Per ogni p(n), q(n) > 0, vale che:

    • Se p(n)p(n) è in O(g(n))O(g(n)) e q(n)q(n) è in O(h(n))O(h(n)), allora f(n)f(n) è in O(g(n)h(n))O(g(n) \cdot h(n)).

    • Se p(n)p(n) è in Ω(g(n))\Omega(g(n)) e q(n)q(n) è in Ω(h(n))\Omega(h(n)), allora f(n)f(n) è in Ω(g(n)h(n))\Omega(g(n) \cdot h(n)).

    • Se p(n)p(n) è in Θ(g(n))\Theta(g(n)) e q(n)q(n) è in Θ(h(n))\Theta(h(n)), allora f(n)f(n) è in Θ(g(n)h(n))\Theta(g(n) \cdot h(n)).

  • Un qualsiasi limite asintotico di f(n)f(n) è uguale al prodotto tra il limite asintotico di p(n)p(n) e di q(n)q(n).

Esercizi svolti sull’algebra asintotica
  1. Trovare il limite asintotico stretto di f(n)=3n2+7f(n) = 3n^2 + 7:
    f(n)=3n2+7=Θ(n2)+Θ(1)=Θ(n2)f(n) = 3n^2 + 7 = \Theta(n^2) + \Theta(1) = \Theta(n^2)

  2. Trovare il limite asintotico stretto di f(n)=3n2n+4n4f(n) = 3n2^n + 4n^4:
    f(n)=3n2n+4n4=Θ(n2n)+Θ(n4)=Θ(n2n)f(n) = 3n2^n + 4n^4 = \Theta(n2^n) + \Theta(n^4) = \Theta(n2^n)

  3. Trovare il limite asintotico stretto di f(n)=22nf(n) = 2^{2n}:
    f(n)=22n=2n2n=Θ(2n)Θ(2n)=Θ(22n)f(n) = 2^{2n} = 2^n \cdot 2^n = \Theta(2^n) \cdot \Theta(2^n) = \Theta(2^{2n})

  4. Trovare il limite asintotico stretto di f(n)=logn(n)+82nlog(n)+3f(n) = logn(n) + 8 \cdot 2^{n\cdot log(n)} + 3: f(n)=logn(n)+82nlog(n)+3=logn(n)+82log(nn)+3f(n) = logn(n) + 8 \cdot 2^{n\cdot log(n)} + 3 = logn(n) + 8 \cdot 2^{log(n^n)} + 3 =logn(n)+8nn+3=Θ(logn(n))+Θ(nn)+Θ(1)=Θ(nn)= logn(n) + 8 \cdot n^n + 3 = \Theta(log_n(n)) + \Theta(n^n) + \Theta(1) = \Theta(n^n)

  5. Trovare il limite asintotico stretto di f(n)=n2log(n)f(n) = n^2 \cdot log(n):
    f(n)=n2log(n)=Θ(n2)Θ(log(n))=Θ(n2log(n))f(n) = n^2 \cdot log(n) = \Theta(n^2) \cdot \Theta(log(n)) = \Theta(n^2 \cdot log(n))

  6. Trovare il limite asintotico stretto di f(n)=3nlog(n)+2n2f(n) = 3n \cdot log(n) + 2n^2:
    f(n)=3nlog(n)+2n2=Θ(n)Θ(log(n))+Θ(n2)=Θ(nlog(n))+Θ(n2)=Θ(n2)f(n) = 3n\cdot log(n) + 2n^2 = \Theta(n)\cdot\Theta(log(n)) + \Theta(n^2) = \Theta(n\cdot log(n)) + \Theta(n^2) = \Theta(n^2)

  7. Trovare il limite asintotico stretto di f(n)=2log(n)/2+5nf(n) = 2^{log(n)/2} + 5n:
    f(n)=2log(n)/2+5n=(2log(n))1/2+5n=n+5n=Θ(n)+Θ(n)=Θ(n)f(n) = 2^{log(n)/2} + 5n = (2^{log(n)})^{1/2} + 5n = \sqrt{n} + 5n = \Theta(\sqrt{n}) + \Theta(n) = \Theta(n)

  8. Trovare il limite asintotico stretto di f(n)=4log(n)f(n) = 4^{log(n)}:
    f(n)=4log(n)=(22)log(n)=(2log(n))2=n2=Θ(n2)f(n) = 4^{log(n)} = (2^2)^{log(n)} = (2^{log(n)})^2 = n^2 = \Theta(n^2)

  9. Trovare il limite asintotico stretto di f(n)=2log(n)f(n) = \sqrt{2^{log(n)}}
    f(n)=2log(n)=2(1/2)log(n)=2log(n)=n=Θ(n)f(n) = \sqrt{2^{log(n)}} = 2^{(1/2)\cdot log(n)} = \sqrt{2^{log(n)}} = \sqrt{n} = \Theta(\sqrt{n})

Sommatorie e Tecniche di dimostrazione
  • Dimostrare o confutare la seguente proposizione
    f(n)=4nf(n) = 4^n è in O(2n)O(2^n)
    Tramite l’algebra asintotica, siamo già in grado di rispondere a tale proposizione::
    4n=22n=2n2n=O(2n)O(2n)=O(22n)4^n = 2^{2n} = 2^{n} \cdot 2^{n} = O(2^n)\cdot O(2^n) = O(2^{2n})
    Dunque, la proposizione è falsa.
    Dimostrazione per assurdo:
    supponiamo che f(n)=O(2n)f(n) = O(2^n). Allora abbiamo che c,n0f(n)c2n,nn0\exists c, n0 | f(n) \leq c \cdot 2^{n} , \forall n \geq n0
    4nc2n4^n \leq c \cdot 2^{n}
    2n2nc2n2^n \cdot 2^{n} \leq c \cdot 2^{n}
    2nc2^{n} \leq c Falso una volta superato un certo valore n0n_0

  • Dimostrare la seguente proposizione f(n)=(n+10)3f(n) = (n + 10)^3 è in Θ(n3)\Theta(n^3)

    • Per dimostrare che sia Θ(n3)\Theta(n^3), dimostriamo che sia in O(n3)O(n^3) e in Ω(n3)\Omega(n^3):

      • Al crescere di n, esisterà un valore n0=10n0 = 10 tale che (n+10)3=(n+n0)3(n+n)3=(2n)3=8n3=O(n3)(n + 10)^3 = (n + n0)^3 \leq (n + n)^3 = (2n)^3 = 8n^3 = O(n^3)

      • Poiché 10 > 0, si vede facilmente che (n+10)3(n+0)3=n3=Ω(n3)(n + 10)^3 \geq (n + 0)^3 = n^3 = \Omega(n^3)
        Poiché f(n)f(n) è sia in O(n3)O(n^3), sia in Ω(n3)\Omega(n^3), allora è anche in Θ(n3)\Theta(n^3)

  • Dimostrare la seguente proposizione Sn=k=1nkSn = \sum{k=1}^n k è in Θ(n2)\Theta(n^2)

    • Come nell’esempio precedente, per dimostrare che sia Θ(n2)\Theta(n^2), dimostriamo che sia in O(n2)O(n^2) e in Ω(n2)\Omega(n^2):

    • Per dimostrare che SnSn è in O(n2)O(n^2), è necessario fare un "salto logico". Partiamo riscrivendo la sommatoria in forma estesa Sn=1+2+3++(n1)+nSn = 1 + 2 + 3 + … + (n − 1) + n
      Notiamo come ogni singolo termine della sommatoria sia n\leq n. Dunque, possiamo scrivere la seguente disequazione:
      1+2+3++(n1)+nn+n+n++n+n1 + 2 + 3 + … + (n − 1) + n \leq n + n + n + … + n + n
      Nella parte destra della disequazione, dunque, abbiamo una somma di n volte n, riscrivibile come nnn \cdot n
      SnnnSnn2Sn \leq n \cdot n \Rightarrow Sn \leq n^2
      A questo punto, ci basta notare che n2n^2 è in O(n2)O(n^2) e quindi che, poiché Snn2Sn \leq n^2, di conseguenza anche SnSn è in O(n2)O(n^2).
      Dimostriamo ora che f(n)=Ω(n2)f(n) = \Omega(n^2) in modo analogo a quello precedente. Riscriviamo nuovamente la sommatoria in forma estesa
      Sn=1+2+3++(n2)+(n1)+nSn = 1 + 2 + 3 + … + (n − 2) + (n − 1) + n Questa volta, notiamo che essa può essere divisa a metà, ottenendo due categorie: 1+2+3+4+5+1 + 2 + 3 + 4 + 5 + … Numeri n2\leq \frac{n}{2} +(n2)+(n+1)+n… + (n − 2) + (n + 1) + n Numeri n2\geq \frac{n}{2} A questo punto, è necessario effettuare un ulteriore "salto logico": sappiamo che tutti i numeri minori di n2\frac{n}{2} sono anche maggiori di 0, mentre quelli maggiori di n2\frac{n}{2} sono ovviamente maggiori di n2\frac{n}{2}. Dunque, possiamo scrivere la seguente disequazione: 1+2+3++(n2)+(n1)+n0+0+0+1 + 2 + 3 + … + (n − 2) + (n − 1) + n \geq 0 + 0 + 0 + … n2\frac{n}{2} volte +n2+n2+n2… + \frac{n}{2} + \frac{n}{2} + \frac{n}{2} n2\frac{n}{2} volte Snn2n2Sn12n2Sn \geq \frac{n}{2} \cdot \frac{n}{2} \Rightarrow Sn \geq \frac{1}{2} n^2 A questo punto, ci basta notare che 12n2\frac{1}{2}n^2 è in Ω(n2)\Omega(n^2) e quindi che, poiché Sn12n2Sn \geq \frac{1}{2}n^2, di conseguenza anche SnSn è in Ω(n2)\Omega(n^2). Poiché SnSn è sia in O(n2)O(n^2), sia in Ω(n2)\Omega(n^2), allora è anche in Θ(n2)\Theta(n^2)

  • Vediamo ora un ulteriore modo per poter dimostrare tale proposizione:
    Sn=k=1nkSn = \sum{k=1}^n k è in Θ(n2)\Theta(n^2)

    • Anche in questa dimostrazione, riscriviamo nuovamente la sommatoria in forma estesa, ma anche in forma invertita:
      Sn=1+2+3++(n2)+(n1)+nSn = 1 + 2 + 3 + … + (n − 2) + (n − 1) + n Sn=n+(n1)+(n2)++3+2+1Sn = n + (n − 1) + (n − 2) + … + 3 + 2 + 1

    • Sommando SnSn con se stessa, otteniamo il seguente risultato: SnSn 1 2 3 …… n − 2 n − 1 n
      SnSn n n − 1 n − 2 …… 3 2 1 2Sn2Sn n + 1 n + 1 n + 1 …… n + 1 n + 1 n + 1
      Dunque,
      2Sn=(n+1)+(n+1)++(n+1)+(n+1)=n(n+1)2S_n = (n + 1) + (n + 1) + … + (n + 1) + (n + 1) = n(n + 1)

    • A questo punto, ci basta sfruttare alcune proprietà algebriche
      2Sn=n(n+1)2Sn = n(n + 1) Sn=n(n+1)2=n2+n2=Θ(n2)Sn = \frac{n(n + 1)}{2} = \frac{n^2 + n}{2} = \Theta(n^2)

  • Dimostrare la seguente proposizione
    Sn=k=0n2kSn = \sum{k=0}^n 2^k è in Θ(2n)\Theta(2^n)

    • Riscriviamo la somma in forma estesa per poi moltiplicarla per 2
      Sn=1+2+22+23++2n1+2nSn = 1 + 2 +2^2 + 2^3 + … + 2^{n-1} + 2^n 2Sn=2(1+2+22+23++2n1+2n)2 \cdot Sn = 2 \cdot (1 + 2 +2^2 + 2^3 + … + 2^{n-1} + 2^n)
      2Sn=2+22+23+24++2n+2n+12S_n = 2 + 2^2 + 2^3 + 2^4 + … + 2^n + 2^{n+1}

    • Gli unici termini non condivisi tra SnSn e 2Sn2Sn sono 1 e 2n+12^{n+1}
      2Sn=2+22+23+24++2n+2n+12Sn = 2 + 2^2 + 2^3 + 2^4 + … + 2^n + 2^{n+1} Sn=1+2+22+23++2nSn = 1 + 2 + 2^2 + 2^3 + … + 2^n

    • Dunque otteniamo che
      Sn=2SnSn=2n+11Sn= 2Sn − S_n = 2^{n+1} − 1

    • A questo punto calcoliamo il limite asintotico del risultato
      Sn=2n+11=2n21=Θ(2n)+Θ(1)=Θ(2n)S_n = 2^{n+1} − 1 = 2^n \cdot 2 − 1 = \Theta(2^n) + \Theta(−1) = \Theta(2^n)

  • Dimostrare la seguente proposizione
    k=1nk2k\sum_{k=1}^n k \cdot 2^k è in Θ(n2n)\Theta(n \cdot 2^n)

    • Riscriviamo in forma estesa e moltiplichiamo per 2
      Sn=21+222+323++(n1)2n1+n2nSn = 2^1 + 2 \cdot 2^2 + 3 \cdot 2^3 + … + (n − 1) \cdot 2^{n−1} + n \cdot 2^n 2Sn=22+223+324++(n1)2n+n2n+12Sn = 2^2 + 2 \cdot 2^3 + 3 \cdot 2^4 + … + (n − 1) \cdot 2^n + n \cdot 2^{n+1}

    • Effettuiamo qualche passaggio algebrico
      Sn=2SnSn=212223242n1+n2n+1Sn = 2Sn − Sn = −2^1 − 2^2 − 2^3 − 2^4 − … − 2^{n−1} + n \cdot 2^{n+1} Sn=(212223242n+n2n+1)−Sn = −(−2^1 − 2^2 − 2^3 − 2^4 − … − 2^n + n \cdot 2^{n+1})
      Sn=21+22+23+24++2nn2n+1−S_n = 2^1 + 2^2 + 2^3 + 2^4 + … + 2^n − n \cdot 2^{n+1}

    • A questo punto, è necessario ricordarsi che nella dimostrazione precedente abbiamo ottenuto che
      k=0n2k=1+21+22+23+24++2n=2n+11\sum{k=0}^n 2^k = 1 + 2^1 + 2^2 + 2^3 + 2^4 + … + 2^n = 2^{n+1} − 1 dunque, possiamo riscrivere Sn−Sn come Sn=21+22+23+24++2nn2n+1=(k=0n2k)1n2n+1−Sn = 2^1+2^2+2^3+2^4+…+2^n−n\cdot2^{n+1} = (\sum{k=0}^n 2^k)−1−n\cdot2^{n+1} =2n+12n2n+1= 2^{n+1}−2−n\cdot2^{n+1} per poi calcolare SnSn
      (Sn)=(2n+12n2n+1)−(−S_n) = −(2^{n+1} − 2 − n \cdot 2^{n+1})
      =2n+1+2+n2n+1= −2^{n+1} + 2 + n \cdot 2^{n+1}

    • Infine, calcoliamo il limite asintotico del risultato
      Sn=2n+1+2+n2n+1=Θ(2n)+Θ(2)+Θ(n2n)=Θ(n2n)S_n = −2^{n+1} + 2 + n \cdot 2^{n+1} = \Theta(2^n) + \Theta(2) + \Theta(n \cdot 2^n) = \Theta(n \cdot 2^n)

  • Dimostrare la seguente proposizione
    k=1nlog(k)\sum_{k=1}^n log(k) è in Θ(nlog(n))\Theta(n \cdot log(n))

    • Riscriviamo la sommatoria in forma estesa in modo da applicare le proprietà dei logaritmi
      Sn=log(1)+log(2)+log(3)++log(n)S_n = log(1) + log(2) + log(3) + … + log(n)
      =log(123n)=log(n!)= log(1 \cdot 2 \cdot 3 \cdot … \cdot n) = log(n!)

    • Dunque, ignorando la costante c, verifichiamo l’ipotesi
      log(n!)nlog(n)log(n!) \leq n \cdot log(n)