Esercizi di Algoritmi e Strutture Dati Moreno Marzolla marzolla@cs.unibo.it 12 ottobre 2010 1 Vero o falso? Per ciascuna delle seguenti affermazioni, dire se è vera o falsa, fornendo una dimostrazione: 1. 3 n = O(2 n ) 2. 2 n = O(3 n ) 3. 2 2n = O(2 n ) 4. 2 n+1 = O(2 n ) 5. log 3 n = Θ(log 2 n) 6. ln n = O(n α ), per ogni α > 0 (ln è il logaritmo naturale). Soluzione 1. Verifichiamo se esiste una costante c > 0 tale che 3 n c2 n per n n 0. Dividendo entrambi i membri per 2 n si richiederebbe the (3/2) n c per una qualche costante c. Poiché n + (3/2) n = +, si ha che la relazione di cui sopra non può essere verificata per n arbitrariamente grande. Concludiamo quindi che l affermazione è falsa. 2. Verifichiamo se esiste una costante c > 0 tale che 2 n c3 n per n n 0. Possiamo scrivere: 2 n c3 n (2/3) n c Osserviamo che per ogni n 0 si ha (2/3) n 1 (infatti la successione (2/3) 0, (2/3) 1, (2/3) 2,... (2/3) i,... è strettamente decrescente), quindi possiamo porre n 0 = 0 e c = 1 per verificare la disuguaglianza. Concludiamo quindi che l affermazione è vera. 1
3. Verifichiamo se esiste una costante c > 0 tale che, per valori sufficientemente grandi di n, valga: 2 2n c2 n Si noti che 2 2n = (2 2 ) n = 4 n. Seguendo la stessa argomentazione del punto precedente, si richiede che 4 n c2 n per una qualche costante c. Concludiamo quindi che l affermazione è falsa. 4. Proviamo a verificare se esiste una costante c > 0 tale che, per valori sufficientemente grandi di n, valga: 2 n+1 c2 n Si noti che 2 n+1 = 2 2 n, per cui possiamo scrivere 2 2 n c2 n che è certamente verificata ponendo ad esempio c = 2, per ogni n 0. Quindi l affermazione è vera. 5. Verifichiamo se c 1 log 2 n log 3 n c 2 log 2 n per opportune costanti c 1 e c 2, e per valori di n sufficientemente grandi. Sia x = log 3 n. Dalla definizione di logaritmo, si ha che 3 x = n. Prendendo il logaritmo in base 2 di entrambi i membri, otteniamo: da cui log 2 (3 x ) = log 2 n x log 2 3 = log 2 n e quindi, ricordando che x era log 3 n si ha: log 3 n = log 2 n log 2 3 In generale, per ogni y > 0, b, c > 1 vale la proprietà di cambio di base dei logaritmi (descritta in appendice nel libro di testo) per cui log a y = log b y log b a Tornando al problema iniziale, si tratta ora di trovare costanti c 1 > 0, c 2 > 0 tali che c 1 log 2 n log 2 n log 2 3 c 2 log 2 n che è verificata se c 1 = c 2 = 1/ log 2 3. Quindi l affermazione è vera. 6. Verifichiamo se ln n cn α, per una opportuna costante c > 0 e per n sufficientemente grande. Per fare questo, studiamo il ite seguente: ln n n + n α 2
Derivando numeratore e denominatore (regola di de l Hôpital) si ottiene ln n n + n α = n + 1/n αn α 1 = n + 1 αn α = 0 Dalla definizione di ite, possiamo concludere che l affermazione ln n = O(n α ) è vera. 2 Il numero mancante Si consideri una permutazione dei primi n numeri interi 1, 2,... n da cui sia tolto un valore. Supponiamo che la permutazione con il valore mancante sia memorizzata in un array di n 1 elementi A[1,... n 1]. Scrivere un algoritmo efficiente che, dato l array A, individua il valore mancante. Ad esempio, dato A = [1, 4, 2, 5], l algoritmo deve restituire il risultato 3; dato A = [7, 1, 8, 6, 2, 3, 4] l algoritmo deve restituire 5. (Suggerimento: è sufficiente una singola scansione dell array A, senza ricorrere ad ulteriori array d appoggio). Soluzione Sfruttiamo l idea seguente: sappiamo che la somma dei primi n numeri interi vale n(n + 1)/2; sottraendo da tale quantità i valori contenuti nel vettore, quello che ci rimane è esattamente il numero mancante. L algoritmo è quindi il seguente: algoritmo trova_mancante( array A[1..n-1] di interi ) -> intero S := n*(n+1)/2; for i:=1 to n-1 do S := S-A[i]; endfor return S; 3 Dimostrazioni per induzione Il seguente esercizio mostra come sia particolarmente importante prestare attenzione a come si fanno le dimostrazioni per induzione Consideriamo la seguente relazione di ricorrenza: 2T ( n/2 ) + 1 n > 1 1 n = 1 È relativamente facile rendersi conto che O(n). Riuscite a dimostrare per induzione che T (n) cn, per una opportuna costante c > 0? Riuscite a dimostrare che T (n) cn b, per opportune costanti c > 0 e b arbitraria? 3
Soluzione Proviamo a dimostrare che T (n) cn per una opportuna costante c > 0. Il caso base T (1) = 1 c è valido per qualunque c 1. Vediamo ora il passo induttivo: 2T ( n/2 ) + 1 2c(n/2) + 1 = cn + 1 A questo punto però non possiamo proseguire affermando cn + 1 cn, perché questo non sarebbe vero. Il problema si risolve usando cn b al posto di cn nella dimostrazione sopra. Infatti, in questo caso il passo induttivo risulta essere 2T ( n/2 ) + 1 2(c(n/2) b) + 1 = cn 2b + 1 cn b che risulta essere verificato se b 1. Il caso base: T (1) = 1 c b risulta verificato scegliendo c b + 1, il che completa la dimostrazione. 4 Problema con il caso base Il seguente esercizio mostra un esempio in cui si presenta un problema con il caso base, facilmente aggirabile. Consideriamo la seguente relazione di ricorrenza: 2T ( n/2 ) + n n > 1 1 n = 1 Dimostrare per induzione che O(n log n), ossia dimostrare che T (n) cn log n per una opportuna costante c > 0 e per ogni n n 0. Soluzione Partiamo alla rovescia, dal passo induttivo: 2T ( n/2 ) + n 2c(n/2) log(n/2) + n per l ipotesi induttiva = cn log(n/2) + n = cn(log n 1) + n = cn log n cn + n = cn log n + n(1 c) cn log n 4
(poiché n è un intero positivo, l ultimo passaggio vale purché sia c > 1). Vediamo ora il caso base: 1 = T (1) c log 1 = 0 Il caso base non funziona per n = 1. Fortunatamente, in questi casi possiamo sfruttare a nostro vantaggio il fatto che la relazione T (n) cn log n non deve necessariamente valere a partire da n = 1, ma solo per n n 0 con n 0 scelto opportunamente. In particolare scegliamo come n 0 un valore per cui valga la relazione che dobbiamo dimostrare. Esaminiamo i valori n = 2, 3,...: T (2) = 2T (1) + 2 = 4 c2 log 2 T (3) = 2T (1) + 3 = 5 c3 log 3 T (4) = 2T (2) + 4 Si noti che possiamo individuare un valore c > 1 che soddisfi le prime due equazioni (ossia T (2) c2 log 2 e T (3) c3 log 3): basta prendere c > max1, 4/(2 log 2), 5/(3 log 3)}. Usando n = 2 e n = 3 come casi base, possiamo sfruttare la dimostrazione del passo induttivo a partire da n = 4 in poi. 5 Analisi di complessità Si consideri la funzione Fun(n), con n 1 intero, definita dal seguente algoritmo ricorsivo: algoritmo Fun(int n) -> int if (n <= 2) then return n; else return Fun(n-1) - 2*Fun(n-2); endif Calcolare un ite superiore e inferiore del tempo di esecuzione T (n) della funzione Fun. Soluzione La relazione di ricorrenza che descrive il tempo T (n) richiesto dall algoritmo di cui sopra è la seguente: c 1 se n 2 T (n 1) + T (n 2) + c 2 se n > 2 Coms i può osservare, la relazione di ricorrenza è la stessa che si ottiene dall analisi dell algoritmo ricorsivo per il calcolo dell n-esimo numero di Fibonacci, per cui si rimanda ai lucidi delle lezioni per il calcolo dei iti superiori 5