Title: Tema 9: Divide y vencer
1Tema 9 Divide y vencerás
- 1. Método general.
- 2. Análisis de tiempos de ejecución.
- 2.1. Análisis general.
- 2.2. Caso recursivo.
- 3. Ejemplos.
- 3.1. Búsqueda del máximo y el mínimo.
- 3.2. Ordenación por mezcla y ordenación rápida.
- 3.3. El problema de selección.
- 3.4. Multiplicación rápida de enteros largos.
- 3.5. Multiplicación rápida de matrices.
2Método general
- La técnica divide y vencerás consiste en
descomponer el problema en un conjunto de
subproblemas más pequeños. Después se resuelven
estos subproblemas y se combinan las soluciones
para obtener la solución para el problema
original. - Esquema general
- divide_venceras (p problema)
- dividir (p, p1, p2, ..., pk)
- para i 1, 2, ..., k
- si resolver (pi)
- solucion combinar (s1, s2, ..., sk)
- Puede ser recursivo siendo resolver una nueva
llamada a divide_venceras - Si el problema es pequeño, entonces se puede
resolver de forma directa. - Ejemplo Torres de Hanoi
3Método general
- Para que pueda aplicarse la técnica divide y
vencerás necesitamos - El problema original debe poder dividirse
fácilmente en un conjunto de subproblemas, del
mismo tipo que el problema original pero con una
resolución más sencilla (menos costosa). - La solución de un subproblema debe obtenerse
independientemente de los otros. - Normalmente los subproblemas deben ser de tamaños
parecidos. Como mínimo necesitamos que haya dos
subproblemas. Si sólo tenemos un subproblema
hablamos de técnicas de reducción (o
simplificación). - Necesitamos un método (más o menos directo) de
resolver los problemas de tamaño pequeño. - Es necesario tener un método de combinar los
resultados de los subproblemas.
4Método general, esquema recursivo
- Normalmente para resolver los subproblemas se
utilizan llamadas recursivas al mismo algoritmo
(aunque no necesariamente). - Esquema recursivo (con división en 2
subproblemas) - divide_venceras (p, q indice)
- var m indice
- si pequeño (p, q)
- solucion solucion_directa (p, q)
- en otro caso
- m dividir (p, q)
- solucion combinar (divide_venceras (p,
m), - divide_venceras (m1, q))
-
5Análisis de tiempos de ejecución
- Para el esquema recursivo, con división en dos
subproblemas - g(n) Si n?n0 es suficientemente pequeño
- t(n)
- 2t(n/2) f(n) En otro caso
- t(n) tiempo de ejecución del algoritmo.
- g(n) tiempo de comprobar si es pequeño y
calcular la solución para el caso base - f(n) tiempo de comprobar si es pequeño y de
dividir el problema y combinar los resultados.
6Análisis de tiempos de ejecución
- Desarrollando tenemos
- Suponiendo que n es potencia de 2, n 2k, y n0
n/2m. -
-
- Si n01, entonces mk
7Análisis de tiempos de ejecución
- Ejemplo 1. La resolución directa se puede hacer
en un tiempo constante y la combinación de
resultados también. - g(n) c f(n) d
- Ejemplo 2. La solución directa se calcula en
O(n2) y la combinación en O(n). - g(n) cn2 f(n) dn
8Análisis de tiempos de ejecución
- Si el problema se divide en a llamadas recursivas
de tamaño n/b, y la combinación requiere f(n)
dn ? O(n), entonces - t(n) at(n/b) dn
- Suponiendo n bk ? k logb n
- t(bk) at(bk-1) dbk
- Podemos deducir que
- O(nlogba) Si a gt b
- t(n) ? O(nlog n) Si a b
- O(n) Si a lt b
- Ejemplo 3. Dividimos en 2 trozos de tamaño n/2
(ordenación por mezcla) - a b 2
- t(n) ? O(nlog n)
- Ejemplo 4. Realizamos 4 llamadas recursivas con
trozos de tamaño n/2. - a 4 b 2
- t(n) ? O(nlog24) O(n2)
9Búsqueda del máximo y del mínimo
- Método directo
- MaxMin (A array 1..N of tipo var Max, Min
tipo) - Max A1
- Min A1
- para i2, 3, ..., N
- si AigtMax
- Max Ai
- en otro caso si AiltMin
- Min Ai
- Contamos el número de comparaciones y
asignaciones. - Comparaciones Asignaciones
10Búsqueda del máximo y del mínimo
- Aplicando divide y vencerás
- MaxMinDV (i, j integer var Max, Min tipo)
- si iltj-1
- mit (ij) div 2
- MaxMinDV (i, mit, Max1, Min1)
- MaxMinDV (mit1, j, Max2, Min2)
- /Combinar/
- si Max1gtMax2
- Max Max1
- en otro caso
- Max Max2
- si Min1ltMin2
- Min Min1
- en otro caso
- Min Min2
- /Caso base/
- en otro caso si ij-1
- si AigtAj
- Max Ai Min Aj
11Búsqueda del máximo y del mínimo
- Comparaciones (entre valores del tipo a ordenar)
usando divide y vencerás. Debemos resolver la
ecuación de recurrencia - t(n) 2t(n/2) 2
-
- Suponiendo n 2k, tenemos
- t(k) 2t(k-1) 2 ? (x-2)(x-1) 0 ?
t(n) C1n C2 - Con condiciones iniciales t(2) 1 t(4) 4
- t(n) 3/2n 2
- Con condiciones iniciales t(1) 0 t(2) 1
- t(n) n 1
- Cuál es el valor de o?
12Búsqueda del máximo y del mínimo
- Asignaciones. La ecuación de recurrencia es la
misma, sólo cambian las condiciones iniciales. - t(2) 2 t(4) 6
- Número de asignaciones
- t(n) 2n 2
- El número de comparaciones es menor en el caso
promedio. - El número de asignaciones es peor en todos los
casos.
13Ordenación por mezcla
- MergeSort (i, j integer)
- / Es pequeño si el tamaño es menor que un caso
base / si pequeño(i, j) - OrdenaciónDirecta(i, j)
- en otro caso
- / El array original es dividido en dos trozos
de tamaño igual (o lo más parecido posible), es
decir ?n/2? y ?n/2? / s (i j) div
2 - / Resolver recursivamente los subproblemas /
MergeSort(i, s) MergeSort(s1, j) - / Mezcla dos listas ordenadas. En O(n)
/ Combina (i, s, j) -
- t(n) t(?n/2?) t(?n/2?) f(n) Con f(n)
? O(n) Suponiendo n potencia de 2,
tenemos t(n) 2t(n/2) an b t(n) ? O(nlog
n)
14Ordenación rápida
- QuickSort (i, j integer)
- / Es pequeño si el tamaño es menor que un caso
base / si pequeño(i, j) - OrdenaciónDirecta(i, j)
- en otro caso
- / El array (i..j) es dividido usando un
procedimiento Pivote, que devuelve un entero l
entre (i, j), tal que Aia ? Al ? Aja, para
ia i..l-1, jal1..j /
Pivote(i,j,l) - / Resolver recursivamente los subproblemas, sin
incluir el pivote / QuickSort(i,
l-1) QuickSort(l1, j) - / No es necesario combinar /
- Aunque no hay coste de combinar los resultados,
la llamada a Pivote tiene un coste O(n). - Las particiones no tienen porqué ser de tamaño
n/2.
15Ordenación rápida
- Pivote (i, j integer var l integer)
- p Ai
- k i
- l j1
- repetir
- k k1
- hasta (Ak gt p) o (k ? j)
- repetir
- l l-1
- hasta (Al ? p)
- mientras k lt l
- intercambiar (k, l)
- repetir
- k k1
- hasta (Ak gt p)
- repetir
- l l-1
- hasta (Al ? p)
- Intercambiar (i, l)
16Ordenación rápida costes.
- Mejor caso.
- Todas las particiones son de tamaño similar,
n/2. - t(n) 2t(n/2) bn c ? ?(nlog n)
- Peor caso.
- Se da cuando la matriz está ordenada o
inversamente ordeanada. En este caso una
partición tiene tamaño 0 y la otra n-1. - t(n) t(n-1) bn c ? O(n2)
- Caso promedio.
- Se puede comprobar que tp(n) ? ?(nlog n).
17El problema de selección
- Sea T1..n un array (no ordenado) de enteros, y
sea s un entero entre 1 y n. El problema de
selección consiste en encontrar el elemento que
se encontraría en la posición s si el array
estuviera ordenado. - Si s ?n/2?, entonces tenemos el problema de
encontrar la mediana de T, es decir el valor que
es mayor que la mitad de los elementos de T y
menor que la otra mitad. - Forma sencilla de resolver el problema de
selección - Ordenar T y devolver el valor Ts. Esto
requeriría ?(nlog n)
18El problema de selección
- Utilizando el procedimiento Pivote podemos
resolverlo en O(n). - Selección (T array 1..n s integer)
- i 1
- j n
- repetir
- Pivote (i, j, l)
- si s lt l
- j l-1
- en otro caso si s gt l
- i l1
- hasta ls
- devolver Tl
- El procedimiento es no recursivo. Además es una
reducción el problema es descompuesto en un solo
subproblema de tamaño menor. - En el mejor caso, el subproblema es de tamaño
n/2 - t(n) t(n/2) an t(n) ? O(n)
- En el peor caso el subproblema es de tamaño n-1
- t(n) t(n-1) an t(n) ? O(n2)
19Multiplicación rápida de enteros largos
- Supongamos que representamos números enteros (de
tamaño arbitrariamente grande) mediante listas de
cifras. - tipo
- EnteroLargo puntero a nodo
- nodo registro
- valor 0..9
- sig EnteroLargo
- Con el algoritmo clásico de multiplicación,
multiplicamos todos los dígitos de un entero por
los del otro y sumamos (con los desplazamientos
adecuados). - El algoritmo tendrá un orden de O(nm),
suponiendo n y m las longitudes de los enteros.
Si las suponemos iguales, entonces O(n2).
20Multiplicación rápida de enteros largos
u w10S x
v y10S z
?n/2?
?n/2?S
- Podemos aplicar la técnica divide y vencerás
- Divide los enteros de tamaño n son divididos en
tamaño n/2. - Solucionar los subproblemas de tamaño n/2.
- Combinar sumar los resultados de los anteriores
(con los desplazamientos adecuados). - Cálculo de la multiplicación con divide y
vencerás - uv 102Swy 10S(wzxy) xz
- El problema de tamaño n es descompuesto en 4
problemas de tamaño n/2. La combinación (sumas y
desplazamientos) se puede realizar en un tiempo
lineal O(n). - t(n) 4t(n/2) dn ? O(nlog24) O(n2), no
mejora el método clásico.
21Multiplicación rápida de enteros largos
- Multiplicación rápida de enteros largos
(Karatsuba y Ofman) - uv 102Swy 10S(w-x)(z-y) wy xz
xz - En este caso se requieren 3 multiplicaciones de
tamaño n/2 - t(n) 3t(n/2) dn ? O(nlog23) ? O(n1.59)
- El método es asintóticamente mejor que el método
clásico. Sin embargo, las constantes son mucho
mayores. La combinación es muy costosa.
22Multiplicación rápida de matrices
- Multiplicar dos matrices cuadradas A, B de
tamaños nxn. - C AxB C(i, j) ? A(i, k)B(k, j) Para
todo i, j 1..n - k1..n
- El método clásico de multiplicación de matrices
requiere O(n3). - Aplicando divide y vencerás, cada matriz es
dividida en cuatro submatrices de tamaño
(n/2)x(n/2) Aij, Bij y Cij.
C11 A11B11 A12B21 C12 A11B12 A12B22 C21
A21B11 A22B21 C22 A21B12 A22B22
x
- Es necesario resolver 8 problemas de tamaño n/2.
La combinación de los resultados requiere un
tiempo de O(n2). - t(n) 8t(n/2) an2
- Resolviéndolo obtenemos que t(n) es O(n3).
23Multiplicación rápida de matrices
- Multiplicación rápida de matrices (Strassen)
- P (A11A22)(B11B22)
- Q (A12A22) B11 C11 P S - T U
- R A11 (B12-B22) C12 R T
- S A22(B21-B11) C21 Q S
- T (A11A12)B22 C22 P R - Q U
- U (A21-A11)(B11B12)
- V (A12-A22)(B21B22)
- El tiempo de ejecución será
- t(n) 7t(n/2) an2
- Resolviéndolo, tenemos que t(n) ? O(nlog27) ?
O(n2.81). - Las constantes que multiplican al polinomio son
mucho mayores (tenemos muchas sumas), por lo que
sólo es mejor cuando la entrada es muy grande.