Tema 5. Divide y vencerás

Anuncio
Algorítmica y Complejidad
Tema 5 – Divide y Vencerás.
Divide y vencerás.
1. Método.
2. Un ejemplo sencillo.
3. Complejidad del método.
4. Ejemplo: El máximo subarray.
5. Ejemplo: Multiplicación de enteros.
2
Divide y vencerás.
1. Método.
2. Un ejemplo sencillo.
3. Complejidad del método.
4. Ejemplo: El máximo subarray.
5. Ejemplo: Multiplicación de enteros.
3
Método.
¡Esquema de
tres etapas!
Dividir.
El problema se divide en varios problemas
similares de menor tamaño.
Resolver.
Si los subproblemas son asumibles se resuelven.
En caso contrario se vuelve a aplicar el método.
Combinar.
Se combinan las soluciones de los subproblemas
para obtener la solución total.
Divide y vencerás.
4
Método.
Características que deben cumplir los problemas para que
se pueda aplicar esta técnica:
El problema se debe poder descomponer en otros
similares pero más pequeños.
Los nuevos problemas deben ser disjuntos.
Debe ser posible combinar las
individuales para obtener la global.
Divide y vencerás.
soluciones
5
Método.
procedure Divide_y_Vencerás (P : problema) is
begin
if P es simple then
Solucionar P;
else
Descomponer P en {P1, P2, ..., Pn};
Divide_y_Vencerás (P1);
Divide_y_Vencerás (P2);
...................
Divide_y_Vencerás (Pn);
Combinar las soluciones de {P1, P2, ..., Pn};
end if;
end Divide_y_Vencerás;
Divide y vencerás.
6
Método.
¿Hasta donde conviene subdividir el problema?
T (n)
Algoritmo
Inmediato
Existirá un umbral n0 por debajo
del cuál será más rápido aplicar
el algoritmo inmediato.
Algoritmo
Div. y Venc.
n0
n
El cálculo de n0 no es trivial y depende de la implementación.
Es habitual utilizar métodos empíricos para su determinación.
Divide y vencerás.
7
Divide y vencerás.
1. Método.
2. Un ejemplo sencillo.
3. Complejidad del método.
4. Ejemplo: El máximo subarray.
5. Ejemplo: Multiplicación de enteros.
8
Un ejemplo sencillo.
Problema:
“Encontrar el valor
máximo en un array
de números enteros."
A:
1
2
3
4
-23
14
31
-3
....
n-1
n
13
-2
La solución inmediata sería:
function Maximo (i, j : integer) return integer is
max : integer := integer'first;
begin
for k in i .. j loop
if A(k) > max then
max := A(k);
end if;
end loop;
return max;
end Maximo;
___________________________
put ("Valor maximo:"); put (Maximo(A'first, A'last));
Divide y vencerás.
9
Un ejemplo sencillo.
Enfoque "divide y vencerás":
1. Dividir el array en dos partes.
2. Hallar el máximo de cada parte.
3. Seleccionar el mayor de los dos.
Se sigue aplicando
de forma recursiva.
Divide y vencerás.
10
Un ejemplo sencillo.
function Maximo (i, j : integer) return integer is
med, max_i, max_d : integer;
begin
end Maximo;
___________________________
put ("Valor maximo:"); put (Maximo(A'first, A'last));
Divide y vencerás.
11
Un ejemplo sencillo.
function Maximo (i, j : integer) return integer is
med, max_i, max_d : integer;
begin
if i=j then
return A(i);
else
end if;
end Maximo;
___________________________
put ("Valor maximo:"); put (Maximo(A'first, A'last));
Divide y vencerás.
12
Un ejemplo sencillo.
function Maximo (i, j : integer) return integer is
med, max_i, max_d : integer;
begin
if i=j then
return A(i);
else
med := (i + j) / 2;
max_i := Maximo (i, med);
max_d := Maximo (med+1, j);
end if;
end Maximo;
___________________________
put ("Valor maximo:"); put (Maximo(A'first, A'last));
Divide y vencerás.
13
Un ejemplo sencillo.
function Maximo (i, j : integer) return integer is
med, max_i, max_d : integer;
begin
if i=j then
return A(i);
else
med := (i + j) / 2;
max_i := Maximo (i, med);
max_d := Maximo (med+1, j);
if max_i > max_d then
return max_i;
else
return max_d;
end if;
end if;
end Maximo;
___________________________
put ("Valor maximo:"); put (Maximo(A'first, A'last));
Divide y vencerás.
14
Divide y vencerás.
1. Método.
2. Un ejemplo sencillo.
3. Complejidad del método.
4. Ejemplo: El máximo subarray.
5. Ejemplo: Multiplicación de enteros.
15
Complejidad del método.
Problema
2
Problema
Problema
a-1
Problema
1
Problema
3
...
Problema
a
T(n/b) + T(n/b ) + T(n/b) + . . . + T(n/b) + T(n/b)
T(n)
aT(n/b)
Descomposición del problema
y
combinación de las soluciones
Divide y vencerás.
O ( n k)
16
Complejidad del método.
En general responderá a esta ecuación:
T(n)=aT(n/b)+O(nk)
: Número de subproblemas
en que se descompone.
a
n/b : Tamaño de cada nuevo
subproblema.
a ≥ 1, b ≥ 2, k ≥ 0
Cuya solución es:
O ( n k ),
T(n)=
a < bk
O ( n k log n ), a = b k
O ( n logb a ),
a > bk
¡Teorema maestro!
Divide y vencerás.
17
Complejidad del método.
Complejidad del ejemplo sencillo: (Enfoque Divide y Vencerás)
function Maximo (i, j : integer) return integer is
med, max_i, max_d : integer;
begin
if i=j then
return A(i);
else
med := (i + j) / 2;
max_i := Maximo (i, med);
max_d := Maximo (med+1, j);
if max_i > max_d then
return max_i;
else
return max_d;
end if;
end if;
end Maximo;
Divide y vencerás.
O(1)
O(1)
18
Complejidad del método.
Complejidad del ejemplo sencillo: (Enfoque Divide y Vencerás)
function Maximo (i, j : integer) return integer is
med, max_i, max_d : integer;
begin
if i=j then
return A(i);
else
med := (i + j) / 2;
max_i := Maximo (i, med);
max_d := Maximo (med+1, j);
if max_i > max_d then
return max_i;
else
return max_d;
end if;
end if;
end Maximo;
Divide y vencerás.
T(n/2)
T(n/2)
19
Complejidad del método.
Complejidad del ejemplo sencillo: (Enfoque Divide y Vencerás)
T(n)=aT(n/b)+O(nk)
a=2
b=2
k=0
T(n)=2T(n/2)+O(1)
a > bk
2 > 20
2 > 1
Divide y vencerás.
O ( n logb a ) = O ( n log2 2 ) = O ( n )
20
Complejidad del método.
Complejidad del ejemplo sencillo: (Enfoque Inmediato)
function Maximo (i, j : integer) return integer is
max : integer := integer'first;
begin
for k in i .. j loop
if A(k) > max then
O
max := A(k);
end if;
end loop;
return max;
end Maximo;
(n)
• Ambos métodos tienen la misma complejidad.
• Divide y Vencerás es más lento por la recursividad.
• En este caso es mejor el Enfoque Inmediato.
Divide y vencerás.
21
Divide y vencerás.
1. Método.
2. Un ejemplo sencillo.
3. Complejidad del método.
4. Ejemplo: El máximo subarray.
5. Ejemplo: Multiplicación de enteros.
22
Ejemplo: El máximo subarray.
Problema:
"Dados varios números que supondremos almacenados en un array, se trata
de encontrar la secuencia de números contiguos cuya suma sea máxima."
Por ejemplo, dado:
A:
1
2
3
4
5
6
7
8
9
10
12
2
-3
-4
-9
8
12
5
-6
1
6
7
8
8
12
5
La solución sería:
cuya suma es 25.
Si existe más de una solución, nos conformaremos
con hallar una de ellas.
Divide y vencerás.
23
Ejemplo: El máximo subarray.
Una solución inmediata:
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
12
2
-3
-4
-9
8
12
5
-6
1
12
2
-3
-4
-9
8
12
5
-6
1
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
12
2
-3
-4
-9
8
12
5
-6
1
12
2
-3
-4
-9
8
12
5
-6
1
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
12
2
-3
-4
-9
8
12
5
-6
1
12
2
-3
-4
-9
8
12
5
-6
1
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
12
2
-3
-4
-9
8
12
5
-6
1
12
2
-3
-4
-9
8
12
5
-6
1
1
2
3
4
5
6
7
8
9
10
12
2
-3
-4
-9
8
12
5
-6
1
1
2
3
4
5
6
7
8
9
10
12
2
-3
-4
-9
8
12
5
-6
1
1
2
3
4
5
6
7
8
9
10
12
2
-3
-4
-9
8
12
5
-6
1
1
2
3
4
5
6
7
8
9
10
12
2
-3
-4
-9
8
12
5
-6
1
Divide y vencerás.
24
Ejemplo: El máximo subarray.
procedure Maximo_Subarray is
..............
begin
max := integer'first;
for i in A'range loop
suma := 0;
for j in i .. A'last loop
suma := suma + A(j);
if suma > max then
max := suma;
inf := i;
sup := j;
end if;
end loop;
end loop;
put ("Indice inferior: ");
put (inf);
put ("Indice superior: ");
put (sup);
put ("Valor de la suma : "); put (max);
end Maximo_Subarray;
Divide y vencerás.
O ( n2 )
new_line;
new_line;
new_line;
25
Ejemplo: El máximo subarray.
Enfoque "divide y vencerás":
Se divide el array en dos partes.
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
Pueden darse tres casos:
1
2
3
4
5
6
7
8
9
10
El subarray está totalmente
en la parte izquierda.
1
8
El subarray está totalmente
en la parte derecha.
2
3
4
5
6
7
8
El subarray
atraviesa la división.
Divide y vencerás.
7
9
10
9
10
Ejemplo: El máximo subarray.
Si el subarray está completamente en uno de los lados, se puede resolver de
forma recursiva, finalizando cuando el tamaño sea de un sólo elemento.
En el otro caso, el subarray tendrá una parte en el lado izquierdo y otra en el
derecho. Las partes se corresponderán con uno de estos casos:
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
12
2
-3
-4
-9
8
12
5
-6
1
12
2
-3
-4
-9
8
12
5
-6
1
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
12
2
-3
-4
-9
8
12
5
-6
1
12
2
-3
-4
-9
8
12
5
-6
1
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
12
2
-3
-4
-9
8
12
5
-6
1
12
2
-3
-4
-9
8
12
5
-6
1
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
12
2
-3
-4
-9
8
12
5
-6
1
12
2
-3
-4
-9
8
12
5
-6
1
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
12
2
-3
-4
-9
8
12
5
-6
1
12
2
-3
-4
-9
8
12
5
-6
1
El máximo subarray estará formado por la unión del de mayor suma en el
lado izquierdo y el de mayor suma del lado derecho.
Divide y vencerás.
Ejemplo: El máximo subarray.
procedure Maximo_Subarray
(E_inf, E_sup : in natural;
S_inf, S_sup : out natural;
S_suma
: out integer) is
........................................
begin
end Maximo_Subarray;
___________________________
Maximo_Subarray (A'first, A'last, inf, sup, max);
Divide y vencerás.
Ejemplo: El máximo subarray.
procedure Maximo_Subarray
(E_inf, E_sup : in natural;
S_inf, S_sup : out natural;
S_suma
: out integer) is
........................................
begin
if E_inf = E_sup then
S_suma := A(E_inf);
else
S_inf := E_inf;
end if;
end Maximo_Subarray;
___________________________
Maximo_Subarray (A'first, A'last, inf, sup, max);
Divide y vencerás.
S_sup := S_inf;
O(1)
Ejemplo: El máximo subarray.
procedure Maximo_Subarray
(E_inf, E_sup : in natural;
S_inf, S_sup : out natural;
S_suma
: out integer) is
........................................
begin
if E_inf = E_sup then
S_suma := A(E_inf);
else
S_inf := E_inf;
S_sup := S_inf;
med := (E_inf + E_sup) / 2;
Maximo_Subarray (E_inf, med, inf_i, sup_i, max_i);
Maximo_Subarray (med + 1, E_sup,inf_d, sup_d, max_d);
Subarray_Comun (E_inf, med, E_sup, inf_c, sup_c, max_c);
end if;
end Maximo_Subarray;
___________________________
Maximo_Subarray (A'first, A'last, inf, sup, max);
Divide y vencerás.
O(1)
O(1)
T(n/2)
T(n/2)
?
Ejemplo: El máximo subarray.
procedure Maximo_Subarray
(E_inf, E_sup : in natural;
S_inf, S_sup : out natural;
S_suma
: out integer) is
........................................
begin
if E_inf = E_sup then
S_suma := A(E_inf);
else
S_inf := E_inf;
S_sup := S_inf;
med := (E_inf + E_sup) / 2;
Maximo_Subarray (E_inf, med, inf_i, sup_i, max_i);
Maximo_Subarray (med + 1, E_sup,inf_d, sup_d, max_d);
Subarray_Comun (E_inf, med, E_sup, inf_c, sup_c, max_c);
if max_i > max_d and max_i > max_c then
S_suma := max_i;
S_inf := inf_i;
S_sup := sup_i;
elsif max_d > max_i and max_d > max_c then
S_suma := max_d;
S_inf := inf_d;
S_sup := sup_d;
else
S_suma := max_c;
S_inf := inf_c;
S_sup := sup_c;
end if;
end if;
end Maximo_Subarray;
___________________________
Maximo_Subarray (A'first, A'last, inf, sup, max);
Divide y vencerás.
O(1)
O(1)
T(n/2)
T(n/2)
?
O(1)
Ejemplo: El máximo subarray.
procedure Subarray_Comun
(E_inf, med, E_sup
S_inf, S_sup
S_suma
........................................
begin
end Subarray_Comun;
Divide y vencerás.
: in natural;
: out natural;
: out integer) is
Ejemplo: El máximo subarray.
procedure Subarray_Comun
(E_inf, med, E_sup
S_inf, S_sup
S_suma
........................................
: in natural;
: out natural;
: out integer) is
begin
suma_izq := integer'first;
suma_tmp := 0;
for i in reverse E_inf .. med loop
suma_tmp := suma_tmp + A(i);
if suma_tmp > suma_izq then
suma_izq := suma_tmp;
S_inf := i;
end if;
end loop;
end Subarray_Comun;
Divide y vencerás.
O(n)
Ejemplo: El máximo subarray.
procedure Subarray_Comun
(E_inf, med, E_sup
S_inf, S_sup
S_suma
........................................
: in natural;
: out natural;
: out integer) is
begin
suma_izq := integer'first;
suma_tmp := 0;
for i in reverse E_inf .. med loop
suma_tmp := suma_tmp + A(i);
if suma_tmp > suma_izq then
suma_izq := suma_tmp;
S_inf := i;
end if;
end loop;
O(n)
suma_der := integer'first;
suma_tmp := 0;
for i in med+1 .. E_sup loop
suma_tmp := suma_tmp + A(i);
if suma_tmp > suma_der then
suma_der := suma_tmp;
S_sup := i;
end if;
end loop;
O(n)
end Subarray_Comun;
Divide y vencerás.
Ejemplo: El máximo subarray.
procedure Subarray_Comun
(E_inf, med, E_sup
S_inf, S_sup
S_suma
........................................
: in natural;
: out natural;
: out integer) is
begin
suma_izq := integer'first;
suma_tmp := 0;
for i in reverse E_inf .. med loop
suma_tmp := suma_tmp + A(i);
if suma_tmp > suma_izq then
suma_izq := suma_tmp;
S_inf := i;
end if;
end loop;
O(n)
suma_der := integer'first;
suma_tmp := 0;
for i in med+1 .. E_sup loop
suma_tmp := suma_tmp + A(i);
if suma_tmp > suma_der then
suma_der := suma_tmp;
S_sup := i;
end if;
end loop;
O(n)
S_suma := suma_izq + suma_der;
end Subarray_Comun;
Divide y vencerás.
O(1)
Ejemplo: El máximo subarray.
Complejidad del enfoque Divide y Vencerás:
T ( n ) = O (1) + O (1) + T (n / 2) + T (n / 2) + O ( ? ) + O (1)
O (n) + O (n) + O (1)
T(n)=2T(n/2)+O(n)
a=2
b=2
k=1
T(n)=aT(n/b)+O(nk)
T (n)
n2
n log n
O ( n 1 log n ) = O ( n log n )
n
Divide y vencerás.
Divide y vencerás.
1. Método.
2. Un ejemplo sencillo.
3. Complejidad del método.
4. Ejemplo: El máximo subarray.
5. Ejemplo: Multiplicación de enteros.
37
Ejemplo: Multiplicación de enteros.
Problema:
"Dados dos números enteros X e Y de n bits cada uno, calcular su producto”
Algoritmo tradicional:
Ejemplo en decimal:
12
x 13
36
12
156
Divide y vencerás.
1100
x 1101
1100
0000
1100
1100
10011100
Complejidad: O ( n 2 )
38
Ejemplo: Multiplicación de enteros.
Algoritmo alternativo 1:
n bits
X
X1
Ejemplo en decimal:
n / 2 bits
n / 2 bits
X0
149238
149
238
X = X1 2n/2 + X0
149238 = 149 106/2 + 238
149000
+ 238
149238
Divide y vencerás.
39
Ejemplo: Multiplicación de enteros.
Los números a multiplicar se pueden representar así:
X = X1 2 n / 2 + X0
Y = Y1 2 n / 2 + Y0
… el producto sería:
X Y = ( X1 2 n / 2 + X0 ) ( Y1 2 n / 2 + Y0 )
… operando:
X Y = X1 Y1 2 n + ( X1 Y0 + X0 Y1 ) 2 n / 2 + X0 Y0
Divide y vencerás.
40
Ejemplo: Multiplicación de enteros.
+
+
+
X Y = X1 Y1 2 n + ( X1 Y0 + X0 Y1 ) 2 n / 2 + X0 Y0
x
x
x
x
3 sumas
O(n)
2 desplazamientos
O(n)
4 multiplicaciones
T(n) = 4 T(n/2) + O(n)
a=4
b=2
k=1
4 > 21
O ( n log 4) = O ( n 2)
2
Divide y vencerás.
41
Ejemplo: Multiplicación de enteros.
Algoritmo alternativo 2:
Ecuación obtenida por el método anterior:
X Y = X1 Y1 2 n + ( X1 Y0 + X0 Y1 ) 2 n / 2 + X0 Y0
( X1 – X0 ) ( Y0 – Y1 ) + X1 Y1 + X0 Y0
X Y = X1 Y1 2 n + (( X1 – X0 )( Y0 – Y1 ) + X1 Y1 + X0 Y0 ) 2 n / 2 + X0 Y0
Divide y vencerás.
42
Ejemplo: Multiplicación de enteros.
+
+
+
+
+
+
X Y = X1 Y1 2 n + (( X1 – X0 )( Y0 – Y1 ) + X1 Y1 + X0 Y0 ) 2 n / 2 + X0 Y0
x
x
x
x
x
Iguales
Iguales
6 sumas (restas)
O(n)
2 desplazamientos
O(n)
5 3multiplicaciones
multiplicaciones
T(n) = 3 T(n/2) + O(n)
a=3
b=2
k=1
3 > 21
O ( n log 3) = O ( n 1,59)
2
Divide y vencerás.
43
Descargar