ANÁLISIS Y DISEÑO DE ALGORITMOS BOLETÍN DE PROBLEMAS: CURSO 2005/2006 DIVIDE Y VENCERÁS Ejercicio 1 Dado un vector ordenado y rotado k veces: diseñar un algoritmo O(log n) que encuentre el elemento mayor del vector, suponiendo que NO conocemos el valor de k. Ejercicio 2 Dados los enteros a[1], a[2], ..., a[n], llamamos moda al que se repite más veces. Obtener un algoritmo mediante la técnica de divide y vencerás que calcule la moda. Para el caso sencillo tenga en cuenta que si tenemos los Enteros ordenados, es posible determinar la moda en tiempo lineal. En otro caso haga uso de las funciones seleccionar-k-esimo y dividir, vistas en clase, para determinar el pivote y los ejemplares en que se divide el problema. Ejercicio 3 Sea a[1..n], un Array de Enteros ordenados en orden estrictamente creciente. Encontrar un algoritmo que necesite un tiempo O(log n) en el caso peor, para determinar la posición i tal que 1 ≤ i ≤ n, con a[i] = i. (Se supone que dicha posición existe.) Ejercicio 4 Dado a: Array[1..n] de Entero, realizar un algoritmo que mediante la técnica de divide y vencerás encuentre, si existe, el elemento mayoritario (aquél que se repite más del 50%) con una complejidad O(n). Téngase en cuenta los algoritmos desarrollados para resolver el problema de la selección del k-ésimo menor elemento de un array. Ejercicio 5 Dado un Vector V[1..n] de palabras ordenadas alfabéticamente de tamaño n, se desea encontrar una palabra dada P, usando un algoritmo de Divide y Vencerás que divide el vector en tres partes, comprueba si la palabra es la buscada en los dos puntos intermedios de la partición y hace la llamada correspondiente para el tramo donde posiblemente se encuentre. Si la palabra no está entonces devolverá un cero y si está devolverá la posición. Se dispone de una función de complejidad Θ(n) denominada compara(a, b), que devuelve 0 si las palabras son iguales, -1 si la primera es menor que la segunda y 1 si la primera es mayor que la segunda. Hallar la ecuación de recurrencia del tiempo de ejecución del algoritmo de Divide y Vencerás anterior y resuelva dicha ecuación de recurrencia para obtener la cota superior en el caso peor. Ejercicio 6 Sea una imagen representada en una matriz cuadrada de tamaño 2k×2k, siendo k>0. Cada elemento de la matriz, representa un píxel, y puede tomar valores 0 para blanco y 1 para negro, que representa el color de dicho cuadrado. Diseñe utilizando la técnica de divide y vencerás, un algoritmo para rotar 90º en el sentido de las agujas del reloj una imagen cualquiera. Calcule la complejidad asintótica del algoritmo, expresándola mediante la notación O, en función del número de píxeles de la imagen, n. Ejemplo de figura rotada 90º en el sentido de las agujas del reloj Ejercicio 7 Dado un conjunto de n puntos representados mediante las coordenadas {x, y} cada uno, que se encuentran recogidos en un Array COOR y están ordenados ascendentemente por la coordenada x. Diseñar mediante la Y técnica de divide y vencerás un algoritmo que devuelva la distancia entre los dos puntos más cercanos. La distancia entre dos puntos es igual a la raíz cuadrada de la suma de la diferencia de abscisas al cuadrado y de las ordenadas al cuadrado. La función divide debe separar el array en dos partes equilibradas en el número de X puntos. Ejercicio 8 Dado un cuadrado de lado n=2k, realizaremos la siguiente partición con él: • • Si k es mayor que 1, se divide en 4 partes, resultando 4 cuadrados de lado 2k-1. Nos quedamos con uno, y a los tres restantes se les aplica el mismo proceso. Si k=1 nos quedamos con este único cuadrado. Codificar un algoritmo de divide y vencerás que determine un array a, de manera que a[i] sea el nº de cuadrados que resultan de lado i. Por ejemplo, si n=16=24, el siguiente dibujo nos muestra que obtendríamos: 1 cuadrado de 8 de lado, 3 cuadrados de 4 de lado y 36 cuadrados de 2 de lado: Determine también la cota exacta del algoritmo. Ejercicio 9 Una matriz de rastreo es una matriz cuadrada de n × n números enteros (sin repeticiones), siendo n una potencia de 2, y en la que se cumple que a1 < b1 < a2 < b2 < a3 < b3 < a4 < b4 y donde además las cuatro submatrices componentes son también matrices de rastreo (véase la figura de la izquierda). Nota: Estas matrices tienen la ventaja de n/2 que permiten búsquedas muy eficientes (de orden logarítmico en vez de cuadrático). a1 a2 Por ejemplo, una matriz de rastreo de orden n/2 4 podría ser: b1 b2 1 2 10 14 a3 a4 5 8 15 19 20 25 55 70 40 43 71 84 b3 b4 Codificar un programa utilizando la técnica de divide y vencerás que determine si una matriz es o no de rastreo. Ejercicio 10 Se dice que un punto P del plano domina a otro Q cuando ambas coordenadas de P son mayores o iguales que las de Q, siendo P ≠ Q. Se dice que un punto P es maximal en una lista de puntos L si no existe ningún punto en L que domine a P. (a) Utilizando la técnica de divide y vencerás, obtener un algoritmo que encuentre todos los puntos maximales de una lista de puntos. En el ejemplo de la figura, los puntos en negrita son los maximales del conjunto de todos los puntos dibujados. y x (b) Calcular la complejidad del algoritmo diseñado en los casos mejor y peor. ¿Cómo influye la ordenación previa de la lista de puntos por una de las coordenadas, si el coste de la ordenación es Θ(n log n)? NOTAS: • Supóngase que todos los puntos son distintos. • Una lista de puntos se representa mediante el tipo LISTAPUNTOS = registro x, y: array[1..N] de Real; np: Entero fregistro, siendo N el número total de puntos y np el número de puntos de la lista, de manera que tales puntos estén en las np primeras posiciones de los arrays x e y, correspondientes a las coordenadas de los puntos. Ejercicio 11 En una empresa de fabricación de vestidos, se dispone de una barra donde se encuentran colgados N vestidos que corresponden a M modelos (M<<N) (M desconocido), se trata de diseñar un algoritmo mediante de divide y vencerás que encuentre el modelo que más se repite y el número de veces que se repite. La información de entrada es un array donde vienen los códigos de barras (entero) de los vestidos. Ejercicio 12 Se dispone de un array de caracteres que representa un texto con palabras separadas por un espacio en blanco. Diseñar un algoritmo de Divide y Vencerás que busque una palabra (array de caracteres) en el array anterior, sabiendo que las palabras del texto no están ordenadas. Analizar la complejidad del algoritmo. Ejercicio 13 Dado un cubo formado por 2n cubitos iguales en tamaño y con diferentes colores, siendo el valor de n=3 ó 6 ó 9 ó 12 ó 15, etc... El cubo viene representado por una matriz tridimensional cubo[2n/3][2n/3][2n/3] de registros de dos enteros. El primero indica el color del cubito, y el segundo indica, para el cubito inferior, izquierdo y delantero de cada cubo de descomposición válida (ver figura), el máximo color de todo ese cubo, y para los demás cubitos aparecerá el valor -1. SE PIDE: Diseñar un algoritmo de divide y vencerás que determine el número de cubitos de un determinado color en un cubo dado. (2, -1) (4, 8) (8, -1) (5, -1) (3, -1) (2, -1) (3, -1) (2, -1) Ejercicio 14 Dado un vector de 4*k enteros desordenados, con todos los valores distintos, siendo k un número entero mayor o igual que uno, diseñar un algoritmo de Divide y Vencerás que devuelva un vector con los k mayores elementos del vector inicial. Analizar la complejidad temporal en los casos mejor, peor y medio. Ejercicio 15 Sea a: array[1..N] de Elemento, no ordenado, se desea obtener los elementos mínimo y máximo de a. Para ello se dispone de la función compara(x, y: Elemento), que devuelve un valor negativo si x < y, positivo si x > y o cero si x = y. Diseñar un algoritmo de Divide y Vencerás para obtener los resultados deseados. El algoritmo debe minimizar el número de llamadas a la función compara. Justificar la solución adoptada. Ejercicio 16 Dado un array de N movimientos de una cuenta corriente, donde se recogen las fechas y la cantidad en euros de los ingresos y reintegros 2/03/04 600.3 5/07/04 -750 9/08/04 1100 16/09/04 -230 13/10/04 420.50 4/11/04 -30.00 27/12/04 -50.20 Si consideramos que saldo parcial de un periodo de tiempo es la suma de ingresos y reintegros durante ese periodo, diseña un algoritmo de divide y vencerás que determine cuál es el saldo parcial máximo de los posibles periodos a considerar para esa cuenta. En el ejemplo este valor máximo sería 1100-230+420.5 euros. Determinar el orden de complejidad de dicho algoritmo.