Mateo Sanabria Ardila
ISIS1105: Diseño y análisis de algoritmos
Dividir y Conquistar
Dividir y Conquistar
Se rompe el problema en subproblemas que son idénticos al original pero de menor tamaño:
-
Se soluciona los subproblemas
-
Se combinan las soluciones, para dar solución al problema original
Dividir y Conquistar
-
Búsqueda Binaria
-
Merge Sort
-
Quicksort
-
Problema: Cantidad de años
-
Problema: Alcanzar el Valhalla
-
Pares de puntos mas cercanos
-
Problema del máximo subarreglo
-
Algoritmo de Strassen (multiplicación de matrices)
Ventajas
-
Se adapta naturalmente a la computación paralela
-
Usualmente hacen uso eficiente de memoria (DEPENDE!)
Desventajas
-
Recursión (Stack overflow)
-
Subproblemas repetidos
Complejidad D&C
Donde a es el número de subproblemas y 1/b es la fracción de los datos a procesar en cada caso recursivo
Dividir y conquistar: Merge Sort
Merge Sort
-
Divide: Divide los n-elementos del arreglo en dos subarreglos de tamaño n/2 cada uno
-
Conquista: Ordena cada una de los subarreglos usado Merge-Sort
-
Combina: Une (Merge) dos subarreglos ordenados para entregar la respuesta ordenada
El caso Base se da cuando se alcanza un arreglo de longitud 1
def merge_sort(array):
if len(array)<2:
return array
else:
midpoint=len(array)//2
left,right = array[:midpoint], array[midpoint:]
left,right = merge_sort(left), merge_sort(right)
return merge(left,right)
Divide y conquista:
def merge(left,right):
result=[]
l_pointer = r_pointer = 0
while l_pointer < len(left) and r_pointer < len(right):
if left[l_pointer] < right[r_pointer]:
result.append(left[l_pointer])
l_pointer+=1
else:
result.append(right[r_pointer])
r_pointer+=1
result.extend(left[l_pointer:])
result.extend(right[r_pointer:])
return result
Combinar (merge):
def merge_sort(array):
if len(array)<2: # <- ?
return array # <- ?
else:
midpoint=len(array)//2 <- #?
left,right = array[:midpoint], array[midpoint:] # <- ?
left,right = merge_sort(left), merge_sort(right) # <- ?
return merge(left,right) # <- ?
Cual es la complejidad del algoritmo?
Cual es la complejidad del algoritmo?
-
Divide: Toma tiempo constate, k.
-
Conquista: El problema de divide en dos subproblemas de tamaño n/2, se tiene 2R(n/2).
-
Combina: Es lineal, luego el costo es, n.
R(n) = \left\{
\begin{array}{ll}
k & \quad n = 1 \\
2R(n/2) + n & \quad x > 1
\end{array}
\right.
Dividir y conquistar: Quick Sort
QUICK Sort
-
Divide: Dividir el arreglo inicial A[0:N] en dos L = A[0:q] y R = A[q+1:N] tal que todo elemento de L es menor o igual que A[q] y todo elemento de R es mayor o igual que A[q].
-
Conquista: Ordenar L y R llamando recursivamente a Quick-Sort.
-
Combina: No es necesario, el arreglo ya se ordeno en los pasos anteriores.
def quick_sort(array,start,end):
if start < end:
q = partition(array,start,end)
quick_sort(array,start,q-1)
quick_sort(array,q+1,end)
Divide:
def partition(array,start,end):
x = array[end]
i = start-1
for j = start to end-1
if array[j] <= x
i += 1
array[i],array[j] = array[j],array[i]
array[i+1],array[end] = array[end],array[i+1]
return i+1
Conquista:
Complejidad de Quick Sort ?
Divide and conques
By Mateo Sanabria Ardila
Divide and conques
- 481