Algoritmos y Estructuras de Datos II, Segundo del Grado de

Anuncio
Algoritmos y Estructuras de Datos II, Segundo del Grado de Ingenierı́a Informática,
Grupo 3.3, Test de Análisis de Algoritmos, marzo 2015
Para cada problema habrá que justificar razonadamente la respuesta que se dé. No son respuestas “razonadas” algunas como: “porque hay otro problema igual en los apuntes”, “porque es evidente”, “porque lo he
comprobado con varios valores”...
1) (2.5 puntos)
Suponemos a un array de enteros [1..n, 1..n].
Dado el código:
for i=1 to n
if(par(i))
for j = i + 1 to n
a[i, i]+ = a[i, j]
endfor
else
for j = i + 1 to n
for k = j to n
a[i, i]+ = a[j, k]
endfor
endfor
endif
endfor
estudiar los órdenes O, Ω, exacto y o-pequeño de su tiempo de ejecución en el caso más favorable,
más desfavorable y promedio.
Solución
Errores comunes:
• Considerar que el caso más favorable es cuando el tamaño es 1.
• Considerar que el caso par es el más favorable y el impar el más desfavorable, o al
revés.
• Asociar una probabilidad a que i sea par o impar. No tiene sentido ya que para cada
valor de i se sabe si es par o impar.
• Analizar el tiempo en función del tamaño del problema n y dejarlo en función de
variables del programa, i, j, k.
• El tiempo promedio no es la media entre el más favorable y el más desfavorable (aunque
puede coincidir por casualidad).
Recomendaciones generales:
• No es necesario responder más de lo que nos piden. Si sólo se nos piden los órdenes
no hay que calcular todos los términos de la expresión del tiempo.
• Cuando hay dos problemas similares (este y el siguiente) se puede reutilizar información
de uno para el otro, y tratar de hacer un enfoque común, de manera que se ahorre
tiempo en la resolución del problema.
Se nos pide estudiar los órdenes de tm , tM y tp , pero la ejecución del algoritmo pasa siempre por
los mismos sitios, independientemente del valor de los datos en el array (no es ası́ en el problema 2,
donde la condición del if depende de los valores del array). Por tanto los tres tiempos coinciden y
vamos a estudiar los órdenes del tiempo, t.
Tenemos un blucle lineal (i = 1 to n), y dentro la mitad de las veces se ejecuta otro bucle lineal
(cuando par(i), se hace j = i+1 to n) y la otra mitad un bucle cuadrático.
Por tantot va a tener forma
cúbica, y sabemos su orden exacto y por tanto O y Ω: t(n) ∈ Ω n3 , t(n) ∈ O n3 y t(n) ∈ θ n3 .
Sólo queda obtener la o-pequeña, para lo que hay que calcular la constante que afecta a n3 . Por
cada pasada en la parte más interna del tercer bucle consideramos que se ejecutan dos instrucciones,
la del paso por el for y la actualización de a[i, i]. Ası́, el término de mayor orden viene dado por:
X
2
n
n
X
X
i=1,3,5... j=i+1 k=j
Pn
j=i+1 (n
n
X
X
1=2
(n − j + 1)
(1)
i=1,3,5... j=i+1
− j + 1) es una progresión aritmética, por tanto
n
X
(n − j + 1) =
j=i+1
n−i+1
(n − i)
2
(2)
Como nos interesa sólo el término de mayor orden, la ecuación 1 se puede aproximar por
n/2
n/2
X
X
n3
2
(2i − 1) ≈
4i2 ≈
(n − i) = (n − 1) + (n − 3) + . . . + 1 =
i =
6
1
1
i=1,3,5...
i=1,3,5...
X
2
2
X
2
2
donde la última aproximación se hace por integración. Por tanto t(n) ∈ o
n3
6
(3)
.
2) (2.5 puntos)
Resolver el problema anterior suponiendo que la condición if(par(i)) se cambia por la
if(par(a[i, i])).
Solución
En este caso sı́ hay caso más favorable y más desfavorable y por tanto también promedio.
El caso más favorable se da cuando los elementos en la diagonal de la matriz (a[i, i]) son todos
pares, pues en ese caso se entra en una rama de ejecución con un único bucle. Igual que en el problema
anterior sólo estudiaremos los términos de mayor orden en el tiempo de ejecución, ya que nos piden
las complejidades asintóticas. El término de mayor orden tiene la forma:
n
n
X
X
2=2
i=1 j=i+1
n
X
(n − i) ≈ n2
(4)
i=1
con lo que tenemos el orden exacto del caso más favorable y por tanto también
el O y el Ω, y la
constante que afecta al término es 1. Por tanto tm (n) ∈ Ω n2 , tm (n) ∈ O n2 , tm (n) ∈ θ n2 , y
tm (n) ∈ o n2 .
El caso más desfavorable se da cuando todos los elementos en la diagonal son impares. En este
caso se entra siempre al else, y la expresión del tiempo queda
2
n
n
n
X
X
X
i=1 j=i+1 k=j
1=2
X
n
X
(n − j + 1)
(5)
i=1,3,5... j=i+1
que es igual a la de la ecuación 1 salvo en el primer sumatorio, que ahora comprende todos los ı́ndices,
no sólo los impares. Haciendo las mismas operaciones que en el problema 1 se llega a una expresión
similar a la de la ecuación 3
Z
n
X
(n − i)2 = (n − 1)2 + (n − 2)2 + . . . + 1 ≈
i=1
1
n
i2 di ≈
n3
3
3
y tM (n) ∈ Ω n3 , tM (n) ∈ O n3 , tM (n) ∈ θ n3 , y tM (n) ∈ o n3 .
El tiempo promedio se obtiene como






n
n
n
n
X
X
X
X
1
2 + 1 1 +
1 +
tp (n) = 1 +
2 + 1 +
2
2
2
i=1
j=i+1
j=i+1
k=j
(6)
(7)
donde estamos contando las instrucciones y considerando la última instrucción de comprobación de
los bucles, aunque no afectarán al orden, y donde los 12 corresponden a la probabilidad de que a[i, i]
sea par o impar. Dado que el término de mayor orden es el de n3 , correspondiente al bucle más
interno, que es el mismo del caso más desfavorable pero eneste caso multiplicaco por 21 , tenemos que
3
tp (n) ∈ Ω n3 , tp (n) ∈ O n3 , tp (n) ∈ θ n3 , y tp (n) ∈ o n6 .
3) (2.5 puntos)
(1.5 puntos) Resolver las ecuaciones de recurrencia indicando los órdenes exactos a los que darı́an
lugar:
a) t(n) = 4t(n − 2) + 1
b) t(n) = 4t(n − 2) + n
c) t(n) = 4t(n − 2) + 2n
d) t(n) = 4t(n − 2) + 2n n
e) t(n) = 4t(n − 2) + 2n + 3n
f) t(n) = 2t(n/9) + 1
g) t(n) = 2t(n/9) + n
h) t(n) = 2t(n/9) + 3n
(0.5 puntos) Ordenar los órdenes obtenidos.
(0.5 puntos) Obtener el o-pequeño para la ecuación a) dados los casos base t(0) = 1 y t(1) = 3.
Solución
Recomendaciones generales:
• En este problema es conveniente tener en cuenta los problemas que son similares, para
minimizar la repetición de cálculos.
Los apartados de a) a e) tienen la misma parte homogénea. Para obtener su contribución a la
ecuación caracterı́stica:
t(n) − 4t(n − 2) = 0 ⇒ x2 − 4 = 0 ⇒ (x − 2)(x + 2) = 0
(8)
y para cada uno de los apartados obtenemos el resto de términos de la ecuación caracterı́stica descomponiendo como suma de bn p(n), con b constante y p(n) un polinomio, los términos de la parte
no homogénea:
a) 1 = 1n ∗ 1 ⇒ b = 1, p(n) = 1, y la ecuación caracterı́stica queda (x − 2)(x + 2)(x − 1) = 0, y la
forma general del tiempo es t(n) = c1 2n + c2 (−2)n + c3 , por lo que el orden será el del término mayor,
2n (consideraremos siempre que la constante del término mayor será positiva).
b) n = 1n ∗ n ⇒ b = 1, p(n) = n, y la ecuación caracterı́stica queda (x − 2)(x + 2)(x − 1)2 = 0, y la
forma general del tiempo es t(n) = c1 2n + c2 (−2)n + c3 + c4 n, por lo que el orden será el del término
mayor, 2n .
c) 2n = 2n ∗ 1 ⇒ b = 2, p(n) = 1, y la ecuación caracterı́stica queda (x − 2)2 (x + 2) = 0, y la forma
general del tiempo es t(n) = c1 2n + c2 n2n + c3 (−2)n , por lo que el orden será el del término mayor,
n2n .
d) 2n n ⇒ b = 2, p(n) = n, y la ecuación caracterı́stica queda (x − 2)3 (x + 2) = 0, y la forma general
del tiempo es t(n) = c1 2n + c2 n2n + c3 n2 2n + c4 (−2)n , por lo que el orden será el del término mayor,
n2 2n .
e) 2n + 3n ⇒ b1 = 2, p1 (n) = 1, b2 = 3, p2 (n) = 1, y la ecuación caracterı́stica queda (x − 2)2 (x +
2)(x − 3) = 0, y la forma general del tiempo es t(n) = c1 2n + c2 n2n + c3 (−2)n + c4 3n , por lo que el
orden será el del término mayor, 3n .
Para los apartados f) a h) se puede hacer el cambio n = 9k , con lo que la parte homogénea queda
tk −2tk−1 = 0 y la ecuación caracterı́stica x−2 = 0. Vemos la contribución a la ecuación caracterı́stica
de la parte no homogénea:
f) 1 = 1k ∗ 1 ⇒ b = 1, p(k) = 1, y la ecuación caracterı́stica queda (x − 2)(x − 1) = 0, y la forma
general del tiempo es tk = c1 2k + c2 , y deshaciendo el cambio t(n) = c1 2log9 n + c2 = c1 nlog9 2 + c2 , por
lo que el orden será el del término mayor, nlog9 2 .
g) 9k = 9k ∗ 1 ⇒ b = 9, p(k) = 1, y la ecuación caracterı́stica queda (x − 2)(x − 9) = 0, y la forma
general del tiempo es tk = c1 2k + c2 9k , y deshaciendo el cambio t(n) = c1 2log9 n + c2 n = c1 nlog9 2 + c2 n,
por lo que el orden será el del término mayor, n.
k
k
h) Este caso es más complicado pues no son iguales 3(9 ) y 39 . Podemos expandir la recurrencia:
k−1
t(n) = 3n + 2t (n/9) = 3n + 23n/9 + 22 t n/92 = . . . = 3n + 23n/9 + . . . + 2k−1 3n/9
+ 2k t(1) (9)
Pk−1
i
El problema ahora es obtener el orden de i=0 2i 3n/9 . Puede que su orden sea 3n , ya que el resto de
términos se obtienen multiplicando el anterior por 2 y disminuyendo la potencia del 3. En total tenemos
k = log9 n términos, y si tomamos el máximo exponente de 2 y de 3 tenemos log9 n ∗ 2log9 n ∗ 3n/9 =
log9 n ∗ nlog9 2 ∗ 3n/9 < n2 3n/9 . Si comparamos este término con 3n
3(8n)/9
3n
(10)
=
lim
n→∞
n→∞ n2 3n/9
n2
que aplicando dos veces la regla de l’Hôpital da ∞, con lo que el orden es 3n .
Nos piden ordenar los órdenes obtenidos. Si hablamos de orden exacto, estos no tiene ordenación
relativa, pues son disjuntos. Por lo tanto suponemos que nos piden ordenar los O. Recordamos
n
log9 2
que los órdenes
son 2n (a y b), n2n (c), n2 2n (d),
(f) y n (g), que se ordenan:
3 (en y h), n
log9 2
n
n
2 n
O n
⊂ O(n) ⊂ O (2 ) ⊂ O (n2 ) ⊂ O n 2 ⊂ O (3 ).
Para obtener las constantes en la expresión del apartado a) no se pueden utilizar los dos casos base,
pues hay que utilizar un caso base y otros desde los que se llegue a él. Además, con tamaños pares se
llegará a 0, y con impares a 1, por lo que no tiene sentido intentar obtener un tiempo combinándolos.
Se trata, por tanto de obtener una expresión para pares y otra para impares.
Si consideramos n par queda t(n) = c1 2n + c2 (−2)n + c3 = c1 2n + c2 2n + c3 , y renombrando
las constantes t(n) = c1 2n + c2 . Con el caso base 0 tenemos t(0) = 1 = c1 + c2 , y con n = 2,
t(2) = 4t(0) + 1 = 5 = c1 4 + c2 . Restando a la segunda ecuación la primera: c1 = 4/3, y t(n) ∈ 34 2n ,
si n es par.
El caso impar se hace de forma similar. t(n) = c1 2n + c2 (−2)n + c3 = c1 2n − c2 2n + c3 , y
renombrando las constantes t(n) = c1 2n + c2 . Con el caso base 1 tenemos t(1) = 3 = c1 2 + c2 , y con
n = 3, t(3) = 4t(1) + 1 = 13 = c1 8 + c2 . Restando a la segunda ecuación la primera: c1 = 5/3, y
t(n) ∈ 35 2n , si n es impar.
lim
4) (2.5 puntos)
Dado a un array de [1..n], estudiar el orden exacto del tiempo de ejecución y de la ocupación de
memoria (suponemos que los datos se pasan por referencia) de la siguiente función cuando se llama
con izq = 1 y der = n:
int funcion(int a[],int izq,int der):
if(izq == der)
return a[izq]
else
cont = 0
for i = izq + 1 to der
cont+ =funcion(a,i,der)
endfor
return cont
endif
Solución
Recomendaciones generales:
• Es conveniente leer con detenimiento lo que se pide y responder a todo. La mayorı́a
no responde a la pregunta sobre la ocupación de memoria. Es normal tratar de hacer
el estudio del tiempo y pensar que con eso acaba el problema.
• Muchas veces es conveniente seguir la ejecución con algún tamaño pequeño para deducir la forma en que trabaja el algoritmo.
En la figura representamos las llamadas que se realizan con un tamaño inicial de 5. Vemos que hay
16 llamadas. Además, con tamaño 1 se hace una llamada, con 2 se hacen 2, con 3 se hacen 4, y con
4 se hacen 8. Ası́, podemos conjeturar que con tamaño n se hacen 2n−1 llamadas, y lo probamos por
inducción. Como para n + 1 se hacen llamadas
tamaños 1 a n, si hasta n el número de llamadas
Pcon
n
es 2n−1 , el total de llamadas para n + 1 es i=1 2i−1 , que es una progresión geométrica de suma
2n . Como el el bucle el número de operaciones cada vez que se pasa es dos (el paso por el bucle y la
actualiización con llamada), queda t(n) ∈ θ (2n ).
5
4
3
2
3
2
1
1
1
2
2
1
1
1
1
1
La ocupación máxima de memoria se obtiene al llegar al final de la rama más profunda de llamadas.
En ese caso hay n llamadas a la vez (las llamadas 5, 4, 3, 2 y 1 en la figura). Como en cada llamada
se necesita espacio para los dos ı́ndices y la referencia del array, tenemos n llamadas con 3 datos en
cada una (suponemos que todos los datos ocupan lo mismo), con lo que la memoria es 3n. Además,
es necesario tener el array a almacenado, lo que son n datos más. Por tanto m(n) ∈ θ(n).
Aunque no es necesario, planteamos cómo estudiar el tiempo planteando una ecuación de recurrencia. El caso base es n = 1, y el número de operaciones t(n) = 2. Cuando no estamos en el caso base
se ejecutan 4 operaciones (comprobación del if, actualización de cont, último paso por el bucle para
no entrar, y return), y las n − 1 pasadas por el bucle con las llamadas correspondientes a problemas
de menor tamaño. En total se tiene:
t(n) = 3 + n + t(n − 1) + t(n − 2) + . . . + t(1)
(11)
No podemos aplicar las técnicas de resolución de recurrencias pues no tenemos un número finito
de términos en t. Si en la ecuación sustituimos n por n − 1 queda:
t(n − 1) = 2 + n + t(n − 2) + t(n − 3) + . . . + t(1)
(12)
y si restamos a la ecuación 11 la 13 queda la recurrencia:
t(n) − t(n − 1) = 1 + n + t(n − 1) ⇒ t(n) − 2t(n − 1) = 1
con ecuación caracterı́stica (x − 2)(x − 1) = 0, con lo que el tiempo es de la forma t(n) ∈ θ (2n ).
(13)
Descargar