CC30A Algoritmos y Estructuras de Datos
Dividir para reinar
Tabulación
Universidad de ChileFacultad de Ciencias Físicas y MatemáticasEscuela de Ingeniería y Ciencias
Dividir para reinarMultiplicación de dos polinomios Problema: multiplicar dos polinomios
de grado n-1.
A(x)=a0+a1x+a2x2+…+an-1xn-1
B(x)=b0+b1x+b2x2+…+bn-1xn-1
C=A(x)*B(x).
Dividir para reinarMultiplicación de dos polinomios Solución trivial O(n2):
float[] c=new float[2*n-1]; // inicializar c[k] en 0 for (i=0; i<n: ++i) for (j=0; j<n; ++j) c[i+j]+=a[i]*b[j];
Dividir para reinarMultiplicación de dos polinomios Algoritmo más eficiente: separar cada
polinomio en 2 partes. Ejemplo:
2
32
)5()32()(
532)(
xxxxA
xxxxA
Dividir para reinarMultiplicación de dos polinomios En general:
El grado de cada polinomio de la suma es (n/2)-1.
2
2
)('')(')(
)('')(')(n
n
xxBxBxB
xxAxAxA
Dividir para reinarMultiplicación de dos polinomios Por lo tanto:
Esto se puede implementar con 4 multiplicaciones de polinomios de tamaño n/2, más kn sumas (para algún k).
))('')('())('')('()( 22
nn
xxBxBxxAxAxC
nn
xxBxAxxBxAxBxAxBxAxC )('')(''))(')('')('')('()(')(')( 2
Dividir para reinarMultiplicación de dos polinomios El número total de operaciones T(n) se
puede escribir como:
¿Qué complejidad temporal tiene el algoritmo?
knn
TnT
24)(
Dividir para reinarMultiplicación de dos polinomios Se resolverá la ecuación:
“Desenrollando” la ecuación:
knqn
TpnT
)(
22
2
1)(
)(
qn
Tpqp
knnT
qn
Tpqn
kpknqn
TpknnT
Dividir para reinarMultiplicación de dos polinomios En general:
Si p>q (nuestro caso):
jj
j
qn
Tpqp
qp
qp
knnT12
...1)(
jj
j
qn
Tp
qpqp
knnT1
1
)(
Dividir para reinarMultiplicación de dos polinomios
Escoger j tal que qj=n (o sea, j=logqn):
Pero:
11
1
)( log
log
Tp
qp
qp
knnT n
n
q
q
n
nn
qnp
qp pnpnn
qqqqq logloglogloglog
Dividir para reinarMultiplicación de dos polinomios Por lo tanto, el algoritmo demora:
Aplicando el resultado a nuestra ecuación, donde p=4 y q=2:
El resultado no es muy interesante…
pqnnT log)(
24log2)( nnnT
Dividir para reinarMultiplicación de dos polinomios PERO si se calcula:
Entonces:
Requiere 3 multiplicaciones recursivas.
nn
xxFxxFxExDxExC )())()()(()()( 2
)('')('')(
)(')(')(
))('')('())('')('()(
xBxAxF
xBxAxE
xBxBxAxAxD
Dividir para reinarMultiplicación de dos polinomios Por lo tanto:
Ejercicio: demostrar T(n) en los casos:– p<q = O(n)– p=q = (n log n)
59.13log2)( nnnT
Recursividad y tabulación
No siempre la recursividad es eficiente. Ejemplo: cálculo de números de
Fibonacci.
1
0
1
0
21
f
f
fff nnn
Recursividad y tabulación
Tabla de valores:n fn2 13 24 35 56 87 138 21… …
n
5
2
51n
Recursividad y tabulación
Solución recursiva:
int F(int n) { if (n<=1) return n; else return F(n-1)+F(n-2); }
Recursividad y tabulación
Esto resulta muy ineficiente. Si T(n) representa el número de sumas ejecutadas para calcular fn, se tiene:
T(0)=0 T(1)=0 T(n)=1+T(n-1)+T(n-2)
Recursividad y tabulación
Tabla de valores para T(n):
¿T(n)=fn-1? Si. (Ejercicio: demostrarlo).
n T(n)0 01 02 13 24 45 76 127 20
Recursividad y tabulación
Luego, el tiempo crece de manera exponencial (muy lento).
El problema es que se está recalculando una y otra vez los mismos valores (ver dibujo en pizarra).
Una forma de evitar esto es anotar los valores calculados en un arreglo.
Recursividad y tabulación
El arreglo debe llenarse de manera ordenada:
int F(int n) { int fib[n+1]; fib[0]=0; fib[1]=1; for (i=2; i<=n; ++i) fib[i]=fib[i-1]+fib[i-2]; }
Recursividad y tabulación
Tiempo del nuevo algoritmo: O(n). Esta idea se llama programación
dinámica cuando se usa para resolver problemas de optimización.
¿Es posible calcular fn más rápido que O(n)? Respuesta: Si.
Recursividad y tabulación
Se tiene que:
Se define una función auxiliar g tal que:
1
0
1
0
21
f
f
fff nnn
0
1
1
1
1
11
g
ffg
gff
nn
nnn
Recursividad y tabulación
Con esto se plantea el siguiente sistema de ecuaciones:
0
1,
01
11
11
1
1
1
1
ff
n
n
Af
n
n
g
f
g
f
g
f
nn
11 fAf n
n
Recursividad y tabulación
An-1 se puede calcular por el método eficiente => Tiempo: O(log n).
Top Related