spessore di un sottovettore
spessore di un sottovettore (es. 6 pdf divide et impera)
In un vettore di interi, si dice spessore del vettore la differenza tra il massimo e il minimo del vettore. Progettare un algoritmo che, preso un vettore di interi ed un intero , trovi un sottovettore (una sequenza di elementi consecutivi del vettore) di lunghezza massima tra quelli di spessore al più . La complessità dell’algoritmo deve essere .
- quindi, dato un sottovettore , definiamo
soluzione in
Una soluzione naïf consiste nel controllare tutti i sottovettori (il che richiederebbe ), ma può essere ottimizzata se si considera una proprietà:
- se ho due sottovettori e e conosco il massimo del primo, non mi serve ricontrollare tutto il secondo vettore ⟶ il massimo sarà dato da (tra il massimo che conosciamo già e il nuovo elemento)
In più, so anche che lo spessore segue il principio di monotonia, ovvero che:
[i,j) \subseteq[i',\,j']\implies spess(v[i,j))\leq spess(v[i',\,j')) \end{align*}$$ Infatti, si ha $$\begin{align*} max(v[i,j))-min(v[i,j)) \leq max(v[i',j'))-min(v[i,j)) \leq max(v[i',j'))-min(v[i',j'))=spess(v[i',j'))
\end{align*}$$
- perché,
- un sottovettore di lunghezza 1 ha spessore 0
- ⟶
- se lo spessore è minore di c, allargo (a destra), se è maggiore di c, stringo da sinistra
- (assumiamo che c sia positivo, quindi la massima lunghezza ha come minimo 1)
maxS = v[0]; minS = v[0]
spess = 0
i = 0; j = 1
maxL = 0; maxi = 0; maxj = 1
# ccontrolla se devi mettere n-1 per evitare out of bounds (v[n] non esiste)
while j < n:
if spess < c:
j += 1
maxS = max(maxS, v[j])
minS = min(minS, v[j])
spess = maxS - minS
if spess < c and j-i > maxL:
maxL = j-i
maxi, maxj = i, j
else:
i += 1
maxS = max(v[i:j]) # Theta(n)
minS = min(v[i:j])
spess = maxS - minS
questo algoritmo ha complessità
Utilizzando maxheap e minheap, si potrebbero estrarre massimi e minimi in log n.
Ma noi vogliamo usare il divide et impera ! Dato un segmento da a ,, lo divido a metà e risolvo i sottoproblemi dati dalle due metà
- il caso base è quello con un sottosegmento di lunghezza 1: lo spessore è 0
ci saranno e [ stessa cosa con l2 r2 ]
- in questo caso, basterebbe prendere il massimo tra gli spessori dei segmenti destro e sinistro
- ma se il più grande segmento si trova a cavallo ? (ovvero, se include l’indice (punto medio))
Per ottenere una ricorrenza in n log n, il tempo di combinazione deve essere T(n) = 2T(n/2) + ? con ? = Theta(n)
Questo problema è semplificato dal fatto che il segmento deve passare per
- è quindi un segmento della forma
- se conosco i massimi e minimi dei due intervalli, lo spessore è dato dalla differenza tra il massimo tra i massimi e il minimo tra i due minimi
- in n, posso calcolarmi tutti gli spessori di tutti gli intervalli del tipo
- mi conviene calcolare (e tenere da parte) non lo spessore, ma il vettore dei massimi e dei minimi a partire da
il candidato deve avere un estremo a sinistra di e uno a destra
quindi fisso r = m e l = inf
- parto dall’ultimo ad essere più piccolo di c per ottimizzare
- parte da m ?? m+1 da destra e inf a sinistra, e sposta la finestra
l = inf; r = m; spess = max((maxL(inf), maxR(m))) - min(minL(inf), minL(sup)))
while l < m and r < sup:
if spess < c:
r += 1
else :
l+=1
spess = riaggiorna_spessore()
massimo insieme indipendente
dato un grafo , un insieme è indipendente se,
NP completo !
vediamo il caso particolare in cui è un albero (connesso e aciclico)
algoritmo greedy
- prendiamo tutte le foglie (sicuramente indipendenti tra loro)
- poto l’albero (dai padri delle foglie)
- prendo le foglie
Dimostrazione:
- ha cardinalità massima
è l’unione tra indipendenti di V1 e V2 v1 è indipendente da v2 per costruzione (non avrà elementi adiacenti alle fogli)
V* è V1* + V2*
Date due sequenze , , trovare la minima sequenza che ha come sottosequenze e .
alberi libri
alberilibri allibberrii
aliberi
(stesso ordine ma non consecutive)
Osserviamo prima la versione ricorsiva e successivamente deriviamo da essa la versione iterativa.
Per ottimizzare la soluzione
def superSeqR(X, i, Y, j):
if i == len(X): return len(Y)-j-1, y[j:]
if j == len(Y): return len(X)-i-1, x[i:]
if X[i] == Y[j]:
l, s = superSeqR(X, i+1, Y, j+1)
return l+1, x[i] + s
lx, sx = superSeqR(X, i+1, Y, j)
ly, sy = superSeqR(X, i, Y, j+1)
if lx < ly:
return lx + 1, x[i]+sx
return ly + 1, y[j]+sy
in cui
- = lunghezza della supersequenza minima tra e
Con casi base:
def superSeqR(X, i, Y, j, T):
if L[i][j] == -1:
if X[i] == Y[j]:
T[i][j] = superSeqR(X, i+1, Y, j+;1, T) + 1
else:
T[i][j] = 1
+ min(superSeqR(X, i+1, Y, j, T), superSeqR(X, i, Y, j+1, T))
return T[i][j]
- il risultato si troverà in