ANÁLISIS Y DISEÑO DE ALGORITMOS BOLETÍN DE PROBLEMAS: ANÁLISIS DE ALGORITMOS Ejercicio 1 Dado el algoritmo: func prob1(a: array de [n] Entero; c: Entero) dev (r: Entero) var inf, sup, i: Entero fin: Lógico alg < fin, inf, sup > := < falso, 1, n > mientras sup >= inf Y NO fin i := (inf + sup) div 2 si a[i] = c: < r, fin > := < i, cierto > | a[i] > c: sup := i – 1 | otras: inf := i + 1 fsi fmientras si NO fin: r := 0 fsi fin (a) Calcular el tiempo de ejecución en los casos mejor, peor y medio. (b) Dar las cotas asintóticas para esos tiempos. Ejercicio 2 Dado el algoritmo: func misterio(n: Entero) dev (r: Entero) var i, j, k: Entero alg r := 0 desde i := 1 hasta n – 1 desde j := i + 1 hasta n desde k := 1 hasta j r := r + 2 fdesde fdesde fdesde fin (a) Calcular el tiempo de ejecución en los casos mejor, peor y medio. (b) Dar las cotas asintóticas para esos tiempos. n Nota: ∑i =1 i 2 = n(n + 1)(2n + 1) / 6 Ejercicio 3 Considerando la función: func f (a: array [1..n] de Entero; prim, ult: Entero) dev (s: Entero) var mitad, terc : Entero alg si prim ≥ ult : s := a[prim] | prim < ult : mitad := ⎣(prim + ult)/2⎦ terc := ⎣(ult – prim)/3⎦ s := a[mitad] + f (a, prim, prim + terc) + f (a, ult – terc, ult) fsi fin (a) Calcular el tiempo de ejecución de la llamada a la función f (a, 1, n), suponiendo que n es potencia de 3. (b) Dar una cota de complejidad para dicho tiempo de ejecución. Ejercicio 4 El tiempo de ejecución de un determinado programa viene dado por la siguiente ecuación en recurrencias: si n = 0 ⎧a T ( n) = ⎨ ⎩2·T ((n − 1) / 2) + b si n > 0 Obtener una expresión no recursiva para T(n), siendo n = 2k − 1 , para valores enteros de k. Indicar el orden de complejidad del algoritmo. Ejercicio 5 Dada la función: func f (n: Entero; a: Real) dev (r: Real) alg si n = 1: r := a | n > 1: r := f (n/2, a+1) – f (n/2, a–1) desde i := 1 hasta n r := r + a * i fdesde fsi fin (a) Calcular el tiempo de ejecución T(n) de una llamada a la misma suponiendo que el valor de n es positivo y potencia de dos. Usar constantes que engloben el tiempo de ejecución de las operaciones elementales. (b) Indicar sus órdenes de complejidad. Ejercicio 6 Dada la siguiente función: func f (a, b: Natural) dev (r: Natural) alg si a = 0 O b = 0: r := 1 | otras: r := 2 * f (a–1, b–1) fsi fin (a) Indicar una expresión para el tamaño del problema, n, en función de los parámetros a y b. (b) Escribir la ecuación en recurrencia del tiempo de ejecución T(n) y resuélvala. Supóngase definidas dos constantes, k1 y k2, que representen los costes de evaluación de las operaciones elementales en los casos trivial y no trivial, respectivamente. Ejercicio 7 Dada la siguiente función: func f (n: Entero) dev (r: Entero) var i, j, z: Entero alg si n < 1: r := 1 | n ≥ 1: z := 0 desde i := 1 hasta n desde j := 1 hasta i ∗ i z := z + 1 fdesde fdesde r := z ∗ (( f (n – 2)) ↑ 2) fsi fin (a) Calcular el tiempo de ejecución T(n) de una llamada a la misma. Usar constantes que engloben el tiempo de ejecución de las operaciones elementales. (En la expresión final pueden dejarse las constantes multiplicativas sin calcular.) (b) Indicar sus órdenes de complejidad. Nota: ↑ representa al operador potencia Ejercicio 8 Dada la función: func f (a: array[1..n] de Entero, k: Entero) dev (r: Entero) {Pre: los valores posibles para a[i] son 0..k (k<n), con igual probabilidad, para i=1..n} var i, j: Entero alg r := 0 desde i := 1 hasta n – k si a[i] = k: desde j := 1 hasta a[i] r := r + a[i + j] fdesde fsi fdesde fin (a) Calcular el tiempo de ejecución T(n, k) para los casos mejor, peor y medio. (b) ¿Qué ocurre al variar k? Discútase tomando como referencia k = 1, k = n/2 y k = n – 1. Ejercicio 9 Se desea calcular el tiempo de ejecución de la función f, cuyo código aparece abajo. func f (ent/sal a: array[1..N] de Entero) dev (s: Entero) alg s := g (a, 0, 1) fin func g (ent/sal a: array[1..N] de Entero, r: Entero, i: Entero) dev (s: Entero) alg si i > N: s := r | i ≤ N: r := r + a[i] s := g (a, r, i+1) fsi fin (a) ¿Cómo escogería el tamaño del problema n para la función recursiva g? (b) Determine el tiempo de ejecución Tg(n) de una llamada recursiva a g. (c) Determine el tiempo de ejecución de ejecución Tf(N) de la función f. Nota: Usar constantes que engloben el tiempo de ejecución de las operaciones elementales. Ejercicio 10 Dado el siguiente algoritmo: proc problema(ent/sal a: array[1..n] de Entero, p: Entero) {Pre: n > 1 Y 0 <= p < n} alg si p >= 1: pasada(a, p) problema(a, p – 1) fsi fin proc pasada(ent/sal a: array[1..n] de Entero, i: Entero) {Pre: n > 1 Y 1 <= i <= n} var temp: Entero alg si i < n Y a[i] > a[i + 1]: temp := a[i] a[i] := a[i + 1] a[i + 1] := temp pasada(a, i + 1) fsi fin (a) Encontrar, razonadamente, T(n) para la llamada problema(a, n–1), en los casos mejor y peor. (b) Obtener, razonadamente, Θ en los casos señalados. NOTAS: • Escoger adecuadamente el tamaño en cada procedimiento. • Justificar los casos peor y mejor. • Añadir las constantes que se crean necesarias para englobar los costes de las operaciones (indicando qué operaciones engloban). En la expresión de T(n) sólo aparecerán estas constantes. Ejercicio 11 Determinar T(n) y la complejidad exacta del siguiente algoritmo, considerando que A(n) ∈ Θ(n) y B(n, m) ∈ Θ(n) func F(n: Entero) dev (i: Entero) var x, j: Real alg si n < 10: i := n | otras: < i, j > := < 1, 0 > mientras (i * i) <= n j := j + A(i) i := i + 1 fmientras x:=n mientras x > 1 j := j + x x := x / 4 desde i := 1 hasta n j := j * B(i, n) fdesde fmientras i := 2 * F(n / 2) + j fsi fin