Divide y Venceras

23
1 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.

description

divide y venceras, teoria algoritmica

Transcript of Divide y Venceras

Page 1: Divide y Venceras

1

Divide y vencerás1. 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.

Page 2: Divide y Venceras

2

Mé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

Page 3: Divide y Venceras

3

Mé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.

Page 4: Divide y Venceras

4

Mé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 (m+1, q));

Page 5: Divide y Venceras

5

Análisis de tiempos de ejecución

• Para el esquema recursivo, con división en dos subproblemas:

g(n) Si n≤n0 es suficientemente pequeñot(n) =

2*t(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.

Page 6: Divide y Venceras

6

Análisis de tiempos de ejecución

• Desarrollando tenemos:Suponiendo que n es potencia de 2, n = 2k, y n0 = n/2m.

• Si n0=1, entonces m=k:

∑−

=

+=1

0

))2/(2()2/(2)(m

i

iimm nfngnt

∑∑−

=

−−

=

+⋅=+=1

0

1

0

))2(2()1())2/(2()2/(2)(k

i

ikik

i

iikk fgnnfngnt

Page 7: Divide y Venceras

7

Aná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) = c·n2; f(n) = d·n

)()1()2())2(2()1()(1

0

1

0

nOndcndcnfgnntk

i

ik

i

iki ∈−⋅+⋅=⋅+⋅=+⋅= ∑∑−

=

=

=+⋅=⋅⋅+⋅=+⋅= ∑∑∑−

=

=

−−

=

−1

0

1

0

1

0

2)22())2(2()1()(k

i

kk

i

ikik

i

iki dcndcnfgnnt

)log(log2 2 nnOnndcnkdcn k ⋅∈⋅⋅+⋅=⋅⋅+⋅=

Page 8: Divide y Venceras

8

Aná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) = d·n ∈ O(n), entonces:

t(n) = a·t(n/b) + d·n

Suponiendo n = bk ⇒ k = logb n

t(bk) = a·t(bk-1) + d·bk

Podemos deducir que:O(nlogba) Si a > b

t(n) ∈ O(n·log n) Si a = bO(n) Si a < b

• Ejemplo 3. Dividimos en 2 trozos de tamaño n/2 (ordenación por mezcla):

a = b = 2t(n) ∈ O(n·log n)

• Ejemplo 4. Realizamos 4 llamadas recursivas con trozos de tamaño n/2.

a = 4; b = 2t(n) ∈ O(nlog24) = O(n2)

Page 9: Divide y Venceras

9

Búsqueda del máximo y del mínimo• Método directo:

MaxMin (A: array [1..N] of tipo; var Max, Min: tipo)Max = A[1]Min = A[1]para i=2, 3, ..., N si A[i]>Max Max = A[i] en otro caso si A[i]<Min Min = A[i]

• Contamos el número de comparaciones y asignaciones.

Comparaciones AsignacionesMejor caso n – 1 ∈ Ω(n) 2 ∈ Ω(1)

Peor caso 2(n - 1) ∈ O(n) n + 1 ∈ O(n)

Caso promedio (n-1) + ∑(i-1)/i = 2(n-1) + ∑1/i ≈≈ 2(n-1) - ln n ∈ O(n)

2 + 2·ln n ∈ O(log n)

Page 10: Divide y Venceras

10

Búsqueda del máximo y del mínimo• Aplicando divide y vencerás:

MaxMinDV (i, j: integer; var Max, Min: tipo)si i<j-1

mit = (i+j) div 2MaxMinDV (i, mit, Max1, Min1)MaxMinDV (mit+1, j, Max2, Min2)

/*Combinar*/si Max1>Max2 Max= Max1en otro caso Max = Max2si Min1<Min2 Min = Min1en otro caso Min = Min2

/*Caso base*/en otro caso si i=j-1

si A[i]>A[j] Max = A[i] ; Min = A[j]en otro caso Max = A[j] ; Min= A[i]

en otro caso Max = A[i] ; Min = Max

Page 11: Divide y Venceras

11

Bú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) = 2·t(n/2) + 2

• Suponiendo n = 2k, tenemos:t(k) = 2·t(k-1) + 2 ⇒ (x-2)·(x-1) = 0 ⇒ t(n) = C1n + C2

• Con condiciones iniciales t(2) = 1; t(4) = 4t(n) = 3/2·n – 2

• Con condiciones iniciales t(1) = 0; t(2) = 1t(n) = n – 1

• ¿Cuál es el valor de o?

Page 12: Divide y Venceras

12

Bú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.

Page 13: Divide y Venceras

13

Ordenación por mezclaMergeSort (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(s+1, 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) = 2·t(n/2) + a·n + bt(n) ∈ O(n·log n)

Page 14: Divide y Venceras

14

Ordenación rápidaQuickSort (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 A[ia] ≤ A[l] ≤ A[ja], para ia = i..l-1, ja=l+1..j */

Pivote(i,j,l)/* Resolver recursivamente los subproblemas, sin incluir el pivote */

QuickSort(i, l-1)QuickSort(l+1, 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.

Page 15: Divide y Venceras

15

Ordenación rápida

Pivote (i, j: integer; var l: integer)p = A[i]k = il = j+1repetir

k:= k+1 hasta (A[k] > p) o (k ≥ j)repetir

l = l-1 hasta (A[l] ≤ p)mientras k < l intercambiar (k, l) repetir

k = k+1 hasta (A[k] > p)

repetir l = l-1

hasta (A[l] ≤ p)Intercambiar (i, l)

Page 16: Divide y Venceras

16

Ordenación rápida: costes.

• Mejor caso.Todas las particiones son de tamaño similar, n/2.

t(n) = 2·t(n/2) + b·n + c ∈ Ω(n·log 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) + b·n + c ∈ O(n2)

• Caso promedio.Se puede comprobar que tp(n) ∈ θ(n·log n).

Page 17: Divide y Venceras

17

El problema de selección

• Sea T[1..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 T[s]. Esto requeriría θ(n·log n)

Page 18: Divide y Venceras

18

El problema de selección• Utilizando el procedimiento Pivote podemos resolverlo en

O(n).Selección (T: array [1..n]; s: integer)

i = 1 j = nrepetir Pivote (i, j, l) si s < l

j = l-1 en otro caso si s > l

i = l+1hasta l=sdevolver T[l]

• 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) + a·n; t(n) ∈ O(n)

• En el peor caso el subproblema es de tamaño n-1:t(n) = t(n-1) + a·n; t(n) ∈ O(n2)

Page 19: Divide y Venceras

19

• 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(n·m), suponiendo n y m las longitudes de los enteros. Si las suponemos iguales, entonces O(n2).

Multiplicación rápida de enteros largos

Page 20: Divide y Venceras

20

Multiplicación rápida de enteros largos

• 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:

u·v = 102S·w·y + 10S·(w·z+x·y) + x·z• 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) = 4·t(n/2) + d·n ∈ O(nlog24) = O(n2), no mejora el método clásico.

w xu

y zv

n/2 n/2=S

u = w·10S + x

v = y·10S + z

Page 21: Divide y Venceras

21

Multiplicación rápida de enteros largos

• Multiplicación rápida de enteros largos (Karatsuba y Ofman):

u·v = 102S·w·y + 10S·[(w-x)·(z-y) + w·y + x·z] + x·z

• En este caso se requieren 3 multiplicaciones de tamaño n/2:t(n) = 3·t(n/2) + d’·n ∈ 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.

Page 22: Divide y Venceras

22

Multiplicació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

k=1..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.

A11 A12

A22A21

xB11 B12

B22B21

=

C11 C12

C22C21

• Es necesario resolver 8 problemas de tamaño n/2. La combinación de los resultados requiere un tiempo de O(n2).

t(n) = 8·t(n/2) + a·n2

• Resolviéndolo obtenemos que t(n) es O(n3).

C11 = A11B11 + A12B21

C12 = A11B12 + A12B22

C21 = A21B11 + A22B21

C22 = A21B12 + A22B22

Page 23: Divide y Venceras

23

Multiplicación rápida de matrices• Multiplicación rápida de matrices (Strassen):

P = (A11+A22)(B11+B22)

Q = (A12+A22) B11 C11 = P + S - T + U

R = A11 (B12-B22) C12 = R + T

S = A22(B21-B11) C21 = Q + S

T = (A11+A12)B22 C22 = P + R - Q + U

U = (A21-A11)(B11+B12)

V = (A12-A22)(B21+B22)

• El tiempo de ejecución será:

t(n) = 7·t(n/2) + a·n2

• 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.