Вы находитесь на странице: 1из 23

Divide y vencers

1. Mtodo general.
2. Anlisis de tiempos de ejecucin.
2.1. Anlisis general.
2.2. Caso recursivo.
3. Ejemplos.
3.1. Bsqueda del mximo y el mnimo.
3.2. Ordenacin por mezcla y ordenacin
rpida.
3.3. El problema de seleccin.
3.4. Multiplicacin rpida de enteros largos.
3.5. Multiplicacin rpida de matrices.
1

Mtodo general
La tcnica divide y vencers consiste en descomponer el problema en
un conjunto de subproblemas ms pequeos. Despus se resuelven
estos subproblemas y se combinan las soluciones para obtener la
solucin 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 pequeo, entonces se puede resolver de forma directa.
Ejemplo: Torres de Hanoi
2

Mtodo general
Para que pueda aplicarse la tcnica divide y vencers
necesitamos:
El problema original debe poder dividirse fcilmente en un
conjunto de subproblemas, del mismo tipo que el problema
original pero con una resolucin ms sencilla (menos costosa).
La solucin de un subproblema debe obtenerse
independientemente de los otros.
Normalmente los subproblemas deben ser de tamaos
parecidos. Como mnimo necesitamos que haya dos
subproblemas. Si slo tenemos un subproblema hablamos de
tcnicas de reduccin (o simplificacin).
Necesitamos un mtodo (ms o menos directo) de resolver
los problemas de tamao pequeo.
Es necesario tener un mtodo de combinar los resultados de
los subproblemas.
3

Mtodo general, esquema recursivo


Normalmente para resolver los subproblemas se utilizan
llamadas recursivas al mismo algoritmo (aunque no
necesariamente).
Esquema recursivo (con divisin en 2 subproblemas):
divide_venceras (p, q: indice)
var m: indice
si pequeo (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));

Anlisis de tiempos de ejecucin


Para el esquema recursivo, con divisin en dos
subproblemas:
g(n)
t(n) =

Si nn0 es suficientemente pequeo

2*t(n/2) + f(n) En otro caso

t(n): tiempo de ejecucin del algoritmo.


g(n): tiempo de comprobar si es pequeo y calcular la
solucin para el caso base
f(n): tiempo de comprobar si es pequeo y de dividir el
problema y combinar los resultados.

Anlisis de tiempos de ejecucin

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

t (n) 2 m g (n / 2 m ) (2 i f (n / 2i ))
i 0

Si n0=1, entonces m=k:


k 1

k 1

i 0

i 0

t (n) 2k g(n / 2k ) (2i f (n / 2i )) n g(1) (2i f (2k i ))


6

Anlisis de tiempos de ejecucin


Ejemplo 1. La resolucin directa se puede hacer en un
tiempo constante y la combinacin de resultados tambin.
g(n) = c;
f(n) = d
k 1

k 1

i 0

i 0

t (n) n g(1) (2i f (2k i )) n c (2i d ) n c d (n 1) O(n)


Ejemplo 2. La solucin directa se calcula en O(n2) y la
combinacin en O(n).
g(n) = cn2; f(n) = dn
k 1

k 1

k 1

t (n) n g(1) (2 f (2 )) n c (2 d 2 ) n c d 2
i

i 0

k i

i 0

k i

i 0

n c d k 2k n c d log 2 n n O(n log n)7

Anlisis de tiempos de ejecucin


Si el problema se divide en a llamadas recursivas de tamao n/b,
y la combinacin 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 > b
t(n) O(nlog n)
Si a = b
O(n)
Si a < b
Ejemplo 3. Dividimos en 2 trozos de tamao n/2 (ordenacin por
mezcla):
a=b=2
t(n) O(nlog n)
Ejemplo 4. Realizamos 4 llamadas recursivas con trozos de
tamao n/2.
a = 4; b = 2
8
t(n) O(nlog24) = O(n2)

Bsqueda del mximo y del mnimo


Mtodo 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 nmero de comparaciones y asignaciones.
Comparaciones
Asignaciones
Mejor caso
n 1 (n)
2 (1)

Peor caso

2(n - 1) O(n)

Caso promedio (n-1) + (i-1)/i = 2(n-1) + 1/i


2(n-1) - ln n O(n)

n + 1 O(n)
2 + 2ln n O(log n)
9

Bsqueda del mximo y del mnimo

Aplicando divide y vencers:

MaxMinDV (i, j: integer; var Max, Min: tipo)


si i<j-1
mit = (i+j) div 2
MaxMinDV (i, mit, Max1, Min1)
MaxMinDV (mit+1, j, Max2, Min2)
/*Combinar*/
si Max1>Max2
Max= Max1
en otro caso
Max = Max2
si Min1<Min2
Min = Min1
en 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

10

Bsqueda del mximo y del mnimo


Comparaciones (entre valores del tipo a ordenar) usando
divide y vencers. Debemos resolver la ecuacin 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
Cul es el valor de o?
11

Bsqueda del mximo y del mnimo


Asignaciones. La ecuacin de recurrencia es la misma,
slo cambian las condiciones iniciales.
t(2) = 2; t(4) = 6
Nmero de asignaciones:
t(n) = 2n 2

El nmero de comparaciones es menor en el caso


promedio.
El nmero de asignaciones es peor en todos los casos.

12

Ordenacin por mezcla


MergeSort (i, j: integer)
/* Es pequeo si el tamao es menor que un caso base */
si pequeo(i, j)
OrdenacinDirecta(i, j)
en otro caso
/* El array original es dividido en dos trozos de tamao igual
(o lo ms 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) = 2t(n/2) + an + b
t(n) O(nlog n)
13

Ordenacin rpida
QuickSort (i, j: integer)
/* Es pequeo si el tamao es menor que un caso base */
si pequeo(i, j)
OrdenacinDirecta(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 tamao n/2.
14

Ordenacin rpida
Pivote (i, j: integer; var l: integer)
p = A[i]
k=i
l = j+1
repetir
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)

15

Ordenacin rpida: costes.


Mejor caso.
Todas las particiones son de tamao 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 particin tiene tamao 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).
16

El problema de seleccin
Sea T[1..n] un array (no ordenado) de enteros, y sea s un
entero entre 1 y n. El problema de seleccin consiste en
encontrar el elemento que se encontrara en la posicin 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 seleccin:
Ordenar T y devolver el valor T[s]. Esto requerira (nlog n)

17

El problema de seleccin

Utilizando el procedimiento Pivote podemos resolverlo en


O(n).
Seleccin (T: array [1..n]; s: integer)
i=1
j=n
repetir
Pivote (i, j, l)
si s < l
j = l-1
en otro caso si s > l
i = l+1
hasta l=s
devolver T[l]
El procedimiento es no recursivo. Adems es una reduccin:
el problema es descompuesto en un solo subproblema de
tamao menor.
En el mejor caso, el subproblema es de tamao n/2:
t(n) = t(n/2) + an; t(n) O(n)
En el peor caso el subproblema es de tamao n-1:
18
2
t(n) = t(n-1) + an; t(n) O(n )

Multiplicacin rpida de enteros largos


Supongamos que representamos nmeros enteros (de
tamao arbitrariamente grande) mediante listas de cifras.
tipo
EnteroLargo = puntero a nodo;
nodo = registro
valor : 0..9
sig : EnteroLargo
Con el algoritmo clsico de multiplicacin, multiplicamos
todos los dgitos 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).
19

Multiplicacin rpida de enteros largos


u

u = w10S + x

v = y10S + z

n/2

n/2=S

Podemos aplicar la tcnica divide y vencers:


Divide: los enteros de tamao n son divididos en tamao
n/2.
Solucionar los subproblemas de tamao n/2.
Combinar: sumar los resultados de los anteriores (con los
desplazamientos adecuados).
Clculo de la multiplicacin con divide y vencers:
uv = 102Swy + 10S(wz+xy) + xz
El problema de tamao n es descompuesto en 4 problemas de
tamao n/2. La combinacin (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 mtodo
20
clsico.

Multiplicacin rpida de enteros largos


Multiplicacin rpida de enteros largos (Karatsuba y
Ofman):
uv = 102Swy + 10S[(w-x)(z-y) + wy + xz] + xz
En este caso se requieren 3 multiplicaciones de tamao n/2:
t(n) = 3t(n/2) + dn O(nlog23) O(n1.59)
El mtodo es asintticamente mejor que el mtodo clsico.
Sin embargo, las constantes son mucho mayores. La
combinacin es muy costosa.

21

Multiplicacin rpida de matrices


Multiplicar dos matrices cuadradas A, B de tamaos nxn.
C = AxB; C(i, j) = A(i, k)B(k, j); Para todo i, j= 1..n
k=1..n

El mtodo clsico de multiplicacin de matrices requiere O(n3).


Aplicando divide y vencers, cada matriz es dividida en cuatro
submatrices de tamao (n/2)x(n/2): Aij, Bij y Cij.
A11

A12

B11

B12

x
A21

A22

C11

C12

C21

C22

=
B21

B22

C11 = A11B11 + A12B21


C12 = A11B12 + A12B22
C21 = A21B11 + A22B21
C22 = A21B12 + A22B22

Es necesario resolver 8 problemas de tamao n/2. La


combinacin de los resultados requiere un tiempo de O(n2).
t(n) = 8t(n/2) + an2
Resolvindolo obtenemos que t(n) es O(n3).
22

Multiplicacin rpida de matrices


Multiplicacin rpida 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 ejecucin ser:
t(n) = 7t(n/2) + an2
Resolvindolo, tenemos que t(n) O(nlog27) O(n2.81).
Las constantes que multiplican al polinomio son mucho
mayores (tenemos muchas sumas), por lo que slo es
23
mejor cuando la entrada es muy grande.

Вам также может понравиться