





















Prepara tus exámenes y mejora tus resultados gracias a la gran cantidad de recursos disponibles en Docsity
Gana puntos ayudando a otros estudiantes o consíguelos activando un Plan Premium
Prepara tus exámenes
Prepara tus exámenes y mejora tus resultados gracias a la gran cantidad de recursos disponibles en Docsity
Prepara tus exámenes con los documentos que comparten otros estudiantes como tú en Docsity
Encuentra los documentos específicos para los exámenes de tu universidad
Estudia con lecciones y exámenes resueltos basados en los programas académicos de las mejores universidades
Responde a preguntas de exámenes reales y pon a prueba tu preparación
Consigue puntos base para descargar
Gana puntos ayudando a otros estudiantes o consíguelos activando un Plan Premium
Comunidad
Pide ayuda a la comunidad y resuelve tus dudas de estudio
Ebooks gratuitos
Descarga nuestras guías gratuitas sobre técnicas de estudio, métodos para controlar la ansiedad y consejos para la tesis preparadas por los tutores de Docsity
Este documento es un material educativo de programación en Python, elaborado por la Universidad de Atacama, que profundiza en algoritmos básicos de búsqueda, ordenamiento y eficiencia algorítmica. Incluye ejercicios prácticos como búsqueda lineal y binaria en listas de números primos, cuadrados perfectos y listas rotadas, así como variantes de ordenamiento burbuja y por selección, incluyendo optimizaciones y aplicaciones específicas (como ordenar strings por longitud o diccionarios por claves). También aborda análisis de complejidad (notación O grande) y problemas integradores que combinan múltiples algoritmos. Cada ejercicio viene acompañado de su solución en Python, explicaciones claras y análisis de eficiencia, lo que lo hace ideal para estudiantes que buscan consolidar sus habilidades en algoritmos y programación estructurada. El documento culmina con ejercicios avanzados y aplicaciones prácticas en sistemas reales como bibliotecas, inventarios y análisis de datos.
Tipo: Exámenes
1 / 29
Esta página no es visible en la vista previa
¡No te pierdas las partes importantes!






















Ejercicios de Ordenamiento (Burbuja y Selecci´on)
Ejercicios de Eficiencia Algor´ıtmica (Notaci´on O Grande)
Ejercicios de Aplicaci´on Pr´actica
1 def es_primo ( n ) : 2 if n < 2: 3 return False 4 for i in range (2 , int ( n **0.5) + 1) : 5 if n % i == 0: 6 return False 7 return True 8 9 def buscar_primo ( lista , objetivo ) : 10 for i in range ( len ( lista ) ) : 11 if lista [ i ] == objetivo and es_primo ( objetivo ) : 12 return i 13 return - 14 15 # Uso : 16 import random 17 primos = [ n for n in range (1 , 1001) if es_primo ( n ) ] 18 random. shuffle ( primos ) 19 print ( buscar_primo ( primos , 17) ) # Ejemplo : busca el primo 17
1 def es_cuadrado_perfecto ( num ) : 2 if num < 0: 3 return False 4 cuadrados = [ i **2 for i in range (1 , 101) ] 5 izquierda , derecha = 0 , len ( cuadrados ) - 1 6 7 while izquierda <= derecha : 8 medio = ( izquierda + derecha ) // 2 9 if cuadrados [ medio ] == num : 10 return True 11 elif cuadrados [ medio ] < num : 12 izquierda = medio + 1 13 else : 14 derecha = medio - 1 15 return False 16 17 # Uso : 18 print ( es_cuadrado_perfecto (64) ) # True (8^2)
10 else : 11 derecha = medio - 1 12 return - 13 14 # Uso : 15 print ( punto_fijo ([ -10 , -5 , 0 , 3 , 7]) ) # 3 ( nums [3] == 3)
1 def buscar_en_matriz ( matriz , objetivo ) : 2 for i in range ( len ( matriz ) ) : 3 for j in range ( len ( matriz [0]) ) : 4 if matriz [ i ][ j ] == objetivo : 5 return (i , j ) 6 return ( -1 , -1) 7 8 # Uso : 9 mat = [[1 , 2 , 3] , [4 , 5 , 6] , [7 , 8 , 9]] 10 print ( buscar_en_matriz ( mat , 5) ) # (1 , 1)
1 def raiz_entera ( num ) : 2 if num < 2: 3 return num 4 5 izquierda , derecha = 2 , num // 2 6 while izquierda <= derecha : 7 medio = ( izquierda + derecha ) // 2 8 cuadrado = medio * medio 9 10 if cuadrado == num : 11 return medio 12 elif cuadrado < num : 13 izquierda = medio + 1 14 else : 15 derecha = medio - 1 16 return derecha # Parte entera por defecto 17 18 # Uso : 19 print ( raiz_entera (10) ) # 3
1 def buscar_por_prefijo ( lista_dict , prefijo ) : 2 prefijo = prefijo. lower () 3 for i , d in enumerate ( lista_dict ) : 4 if d [ " nombre " ]. lower (). startswith ( prefijo ) : 5 return i 6 return - 7 8 # Uso : 9 personas = [{ " id " : 1 , " nombre " : " Ana " } , { " id " : 2 , " nombre " : " Carlos " }] 10 print ( buscar_por_prefijo ( personas , " a " ) ) # 0
1 def buscar_casi_ordenada ( nums , objetivo , k =3) : 2 i = 0 3 while i < len ( nums ) : 4 if nums [ i ] == objetivo : 5 return i 6 # Salta hasta k posiciones adelante 7 i += max (1 , abs ( nums [ i ] - objetivo ) // k ) 8 return - 9 10 # Uso : 11 nums = [10 , 12 , 15 , 11 , 14 , 13 , 16] 12 print ( buscar_casi_ordenada ( nums , 14) ) # 4
Soluciones de Ordenamiento (Burbuja y Selecci´on)
1 def burbuja_contador ( lista ) : 2 n = len ( lista ) 3 intercambios = 0 4 for i in range (n -1) : 5 for j in range (n -i -1) : 6 if lista [ j ] > lista [ j +1]: 7 lista [ j ] , lista [ j +1] = lista [ j +1] , lista [ j ] 8 intercambios += 1 9 return intercambios 10 11 # Uso : 12 import random 13 datos = random. sample ( range (1 , 100) , 10) 14 print ( f " Lista original : { datos } " ) 15 print ( f " Intercambios : { burbuja_contador ( datos ) } " ) 16 print ( f " Lista ordenada : { datos } " )
1 def seleccion_estable ( lista ) : 2 n = len ( lista ) 3 for i in range ( n ) : 4 min_idx = i 5 # Busca el m n i m o en el resto 6 for j in range ( i +1 , n ) : 7 if lista [ j ] < lista [ min_idx ]: 8 min_idx = j 9 # Inserta en p o s i c i n actual sin swap para estabilidad 10 valor = lista. pop ( min_idx ) 11 lista. insert (i , valor ) 12 return lista 13 14 # Uso : 15 datos = [(3 , ’a ’) , (2 , ’b ’) , (3 , ’c ’) , (1 , ’d ’) ] 16 print ( seleccion_estable ( datos ) ) # [(1 , ’d ’) , (2 , ’b ’) , (3 , ’a ’) , (3 , ’c ’) ]
11 # Uso : 12 personas = [{ " edad " : 25} , { " edad " : 18} , { " edad " : 30}] 13 print ( seleccion_diccionarios ( personas , " edad " ) ) # [{ ’ edad ’: 18} , ...]
1 def shaker_sort ( lista ) : 2 izquierda = 0 3 derecha = len ( lista ) - 1 4 while izquierda < derecha : 5 # Ida ( izq -> der ) 6 for i in range ( izquierda , derecha ) : 7 if lista [ i ] > lista [ i +1]: 8 lista [ i ] , lista [ i +1] = lista [ i +1] , lista [ i ] 9 derecha -= 1 10 11 # Vuelta ( der -> izq ) 12 for i in range ( derecha , izquierda , -1) : 13 if lista [ i ] < lista [i -1]: 14 lista [ i ] , lista [i -1] = lista [i -1] , lista [ i ] 15 izquierda += 1 16 return lista 17 18 # Uso : 19 datos = [5 , 1 , 4 , 2 , 8 , 0 , 2] 20 print ( shaker_sort ( datos ) ) # [0 , 1 , 2 , 2 , 4 , 5 , 8]
1 def suma_digitos ( n ) : 2 return sum ( int ( d ) for d in str ( abs ( n ) ) ) 3 4 def seleccion_personalizado ( lista ) : 5 n = len ( lista ) 6 for i in range ( n ) : 7 min_idx = i 8 for j in range ( i +1 , n ) : 9 # Compara s e g n suma de d g i t o s 10 condicion = ( suma_digitos ( lista [ j ]) % 2 == 0) 11 if ( condicion and lista [ j ] < lista [ min_idx ]) or ( not condicion and lista [ j ] > lista [ min_idx ]) : 12 min_idx = j 13 lista [ i ] , lista [ min_idx ] = lista [ min_idx ] , lista [ i ] 14 return lista 15 16 # Uso : 17 numeros = [12 , 34 , 23 , 56] 18 print ( seleccion_personalizado ( numeros ) ) # [12 , 23 , 56 , 34]
1 def burbuja_matriz ( matriz , por_filas = True ) : 2 if por_filas : 3 for fila in matriz : 4 n = len ( fila ) 5 for i in range (n -1) : 6 for j in range (n -i -1) : 7 if fila [ j ] > fila [ j +1]:
8 fila [ j ] , fila [ j +1] = fila [ j +1] , fila [ j ] 9 else : 10 n_filas = len ( matriz ) 11 n_cols = len ( matriz [0]) 12 for col in range ( n_cols ) : 13 for i in range ( n_filas -1) : 14 for j in range ( n_filas -i -1) : 15 if matriz [ j ][ col ] > matriz [ j +1][ col ]: 16 # Swap entre filas 17 matriz [ j ][ col ] , matriz [ j +1][ col ] = matriz [ j +1][ col ] , matriz [ j ][ col ] 18 return matriz 19 20 # Uso : 21 mat = [[3 , 1 , 2] , [6 , 4 , 5] , [9 , 7 , 8]] 22 print ( " Filas ordenadas : " , burbuja_matriz ( mat ) ) 23 print ( " Columnas ordenadas : " , burbuja_matriz ( mat , False ) )
1 def busqueda_binaria_posicion ( lista , objetivo , inicio , fin ) : 2 while inicio <= fin : 3 medio = ( inicio + fin ) // 2 4 if lista [ medio ] == objetivo : 5 return medio 6 elif lista [ medio ] < objetivo : 7 inicio = medio + 1 8 else : 9 fin = medio - 1 10 return inicio # P o s i c i n de i n s e r c i n 11 12 def seleccion_hibrido ( lista ) : 13 n = len ( lista ) 14 for i in range ( n ) : 15 min_val = min ( lista [ i :]) 16 min_idx = lista. index ( min_val , i ) 17 # Busca p o s i c i n ptima con b s q u e d a binaria 18 pos = busqueda_binaria_posicion ( lista , min_val , 0 , i ) 19 # Inserta en p o s i c i n correcta 20 lista. pop ( min_idx ) 21 lista. insert ( pos , min_val ) 22 return lista 23 24 # Uso : 25 datos = [64 , 25 , 12 , 22 , 11] 26 print ( seleccion_hibrido ( datos ) ) # [11 , 12 , 22 , 25 , 64]
Soluciones de Eficiencia Algor´ıtmica (Notaci´on O Grande)
1 import math 2 3 def analisis_busqueda ( n =1 _000_000 ) : 4 lineal = n /2 # Promedio 5 binaria = math. log2 ( n ) 6 return f " Lineal : { lineal :.0 f } comparaciones \ nBinaria : { binaria :.0 f } comparaciones "
1 def seleccion_adaptativo ( lista , k =10) : 2 n = len ( lista ) 3 for i in range ( n ) : 4 min_idx = i 5 # Solo verifica k elementos adelante 6 for j in range ( i +1 , min ( i +1+ k , n ) ) : 7 if lista [ j ] < lista [ min_idx ]: 8 min_idx = j 9 lista [ i ] , lista [ min_idx ] = lista [ min_idx ] , lista [ i ] 10 return lista
1 def busqueda_infinita ( func , objetivo ) : 2 # Encuentra rango 3 bajo , alto = 0 , 1 4 while func ( alto ) < objetivo : 5 bajo = alto 6 alto *= 2 7 # B s q u e d a binaria e s t n d a r 8 while bajo <= alto : 9 medio = ( bajo + alto ) // 10 val = func ( medio ) 11 if val == objetivo : 12 return medio 13 elif val < objetivo : 14 bajo = medio + 1 15 else : 16 alto = medio - 1 17 return - 18 19 # Ejemplo : lista i m p l c i t a f ( i ) = i ^ 20 print ( busqueda_infinita ( lambda x : x *x , 25) ) # 5
1 from timeit import repeat 2 3 def comparar_pequenos () : 4 setup = " from random import shuffle ; x = list ( range (10) ) ; shuffle ( x ) " 5 pruebas = { 6 ’ S e l e c c i n ’: " y = x [:]; n = len ( y ) ; " 7 " for i in range ( n ) : min_idx = i ; " 8 " for j in range ( i +1 , n ) : " 9 " if y [ j ] < y [ min_idx ]: min_idx = j ; " 10 " y [ i ] , y [ min_idx ]= y [ min_idx ] , y [ i ] " , 11 ’ Burbuja ’: " y = x [:]; n = len ( y ) ; " 12 " for i in range (n -1) : " 13 " for j in range (n -i -1) : " 14 " if y [ j ] > y [ j +1]: y [ j ] , y [ j +1]= y [ j +1] , y [ j ] " 15 } 16 return { k : min ( repeat (v , setup , number =1000) ) for k , v in pruebas. items () } 17 18 print ( comparar_pequenos () ) # S e l e c c i n suele ser m s r p i d o para n 10
1 def busqueda_lineal_early ( lista , objetivo ) : 2 for i , elemento in enumerate ( lista ) : 3 if elemento == objetivo : 4 return i 5 if elemento > objetivo : # Early exit si lista e s t ordenada 6 break 7 return - 8 9 # Mejor caso ( primer elemento ) : O (1) 10 # Peor caso ( ltimo o no existe ) : O ( n )
1 def memoria_algoritmos () : 2 algoritmos = { 3 ’ Burbuja ’: ’ Solo necesita O (1) espacio adicional para swaps ’ , 4 ’ S e l e c c i n ’: ’O (1) espacio , similar a burbuja ’ , 5 ’ B s q u e d a Binaria ’: ’O (1) en i m p l e m e n t a c i n iterativa , O ( log n ) en recursiva ’ 6 } 7 return algoritmos
1 def peores_casos () : 2 casos = { 3 ’ Burbuja ’: ’ Lista en orden inverso : m x i m o n m e r o de swaps ’ , 4 ’ S e l e c c i n ’: ’ Lista donde el m n i m o siempre e s t al final : m x i m o comparaciones ’ , 5 ’ B s q u e d a Binaria ’: ’ Elemento no existe en lista ’ 6 } 7 return casos
Soluciones Integradoras (B´usqueda, Ordenamiento y Eficien-
cia)
1 def ordenar_empleados ( empleados ) : 2 # Ordenamiento por s e l e c c i n por salario 3 n = len ( empleados ) 4 for i in range ( n ) : 5 min_idx = i 6 for j in range ( i +1 , n ) : 7 if empleados [ j ][ ’ salario ’] < empleados [ min_idx ][ ’ salario ’ ]: 8 min_idx = j 9 empleados [ i ] , empleados [ min_idx ] = empleados [ min_idx ] , empleados [ i ] 10 return empleados 11
22 23 print ( medir_tiempo (1000) )
1 def encontrar_duplicados ( lista ) : 2 lista_ordenada = sorted ( lista ) # Timsort O ( n log n ) 3 duplicados = [] 4 for i in range (1 , len ( lista_ordenada ) ) : 5 if lista_ordenada [ i ] == lista_ordenada [i -1]: 6 duplicados. append ( lista_ordenada [ i ]) 7 return list ( set ( duplicados ) ) # Eliminar duplicados de resultados 8 9 # Uso : 10 print ( encontrar_duplicados ([3 , 1 , 2 , 3 , 4 , 2]) ) # [2 , 3]
1 def interseccion_ordenada ( lista1 , lista2 ) : 2 lista1_sorted = sorted ( lista1 ) 3 lista2_sorted = sorted ( lista2 ) 4 resultado = [] 5 i = j = 0 6 # Merge similar a mergesort 7 while i < len ( lista1_sorted ) and j < len ( lista2_sorted ) : 8 if lista1_sorted [ i ] == lista2_sorted [ j ]: 9 resultado. append ( lista1_sorted [ i ]) 10 i += 1 11 j += 1 12 elif lista1_sorted [ i ] < lista2_sorted [ j ]: 13 i += 1 14 else : 15 j += 1 16 return resultado 17 18 # Uso : 19 print ( interseccion_ordenada ([1 , 2 , 3 , 4] , [3 , 4 , 5]) ) # [3 , 4]
1 def encontrar_faltante ( lista ) : 2 izquierda , derecha = 0 , len ( lista ) - 1 3 while izquierda <= derecha : 4 medio = ( izquierda + derecha ) // 2 5 if lista [ medio ] == medio + 1: # Si lista [0] d e b e r a ser 1 6 izquierda = medio + 1 7 else : 8 derecha = medio - 1 9 return izquierda + 1 # El faltante 10 11 # Uso : 12 print ( encontrar_faltante ([1 , 2 , 3 , 5]) ) # 4
1 def ordenar_buscar_matriz ( matriz , objetivo ) : 2 # Ordenar cada fila con burbuja 3 for fila in matriz : 4 n = len ( fila ) 5 for i in range (n -1) : 6 for j in range (n -i -1) : 7 if fila [ j ] > fila [ j +1]: 8 fila [ j ] , fila [ j +1] = fila [ j +1] , fila [ j ] 9 10 # Buscar en cada fila con binaria 11 resultados = [] 12 for i , fila in enumerate ( matriz ) : 13 izquierda , derecha = 0 , len ( fila ) - 14 while izquierda <= derecha : 15 medio = ( izquierda + derecha ) // 2 16 if fila [ medio ] == objetivo : 17 resultados. append (( i , medio ) ) 18 break 19 elif fila [ medio ] < objetivo : 20 izquierda = medio + 1 21 else : 22 derecha = medio - 1 23 return resultados 24 25 # Uso : 26 mat = [[3 , 1 , 2] , [6 , 4 , 5]] 27 print ( ordenar_buscar_matriz ( mat , 4) ) # [(1 , 1) ]
1 def encontrar_pico ( lista ) : 2 # Primero ordenamos con s e l e c c i n 3 n = len ( lista ) 4 for i in range ( n ) : 5 min_idx = i 6 for j in range ( i +1 , n ) : 7 if lista [ j ] < lista [ min_idx ]: 8 min_idx = j 9 lista [ i ] , lista [ min_idx ] = lista [ min_idx ] , lista [ i ] 10 11 # Luego b s q u e d a lineal del pico 12 for i in range (1 , n -1) : 13 if lista [i -1] < lista [ i ] > lista [ i +1]: 14 return lista [ i ] 15 return None 16 17 # V e r s i n ptima sin ordenar ( O ( n ) ) 18 def pico_optimo ( lista ) : 19 for i in range (1 , len ( lista ) -1) : 20 if lista [i -1] < lista [ i ] > lista [ i +1]: 21 return lista [ i ] 22 return None 23 24 # Uso : 25 print ( encontrar_pico ([1 , 3 , 5 , 2]) ) # 5 ( v e r s i n ordenada ) 26 print ( pico_optimo ([1 , 3 , 5 , 2]) ) # 5 ( v e r s i n ptima )
1 def subcadena_comun ( lista1 , lista2 ) :
4 # Fase de s e l e c c i n : encontrar m n i m o 5 min_idx = i 6 for j in range ( i +1 , n ) : 7 if lista [ j ] < lista [ min_idx ]: 8 min_idx = j 9 # Fase de burbuja : llevar el m n i m o a su p o s i c i n 10 for k in range ( min_idx , i , -1) : 11 lista [ k ] , lista [k -1] = lista [k -1] , lista [ k ] 12 return lista 13 14 # Uso : 15 datos = [64 , 34 , 25 , 12 , 22 , 11 , 90] 16 print ( hibrido_burbuja_seleccion ( datos. copy () ) )
1 def busqueda_arbol_implicito ( lista , objetivo ) : 2 i = 1 # R a z en p o s i c i n 1 ( ndice 0 - based ) 3 n = len ( lista ) 4 while i < n : 5 if lista [ i ] == objetivo : 6 return i 7 elif lista [ i ] > objetivo : 8 i = 2* i + 1 # Hijo izquierdo 9 else : 10 i = 2* i + 2 # Hijo derecho 11 return - 12 13 # rbol binario completo representado como lista : 14 # 5 15 # /
16 # 3 8 17 # / \ /
18 # 1 4 7 9 19 arbol = [5 , 3 , 8 , 1 , 4 , 7 , 9] 20 print ( busqueda_arbol_implicito ( arbol , 4) ) # 4
1 def seleccion_inplace ( lista ) : 2 n = len ( lista ) 3 for i in range ( n ) : 4 # Encuentra el m n i m o sin almacenar ndices adicionales 5 min_val = lista [ i ] 6 min_pos = i 7 for j in range ( i +1 , n ) : 8 if lista [ j ] < min_val : 9 min_val = lista [ j ] 10 min_pos = j 11 # Intercambio usando XOR para evitar variable temporal 12 if min_pos != i : 13 lista [ i ] ^= lista [ min_pos ] 14 lista [ min_pos ] ^= lista [ i ] 15 lista [ i ] ^= lista [ min_pos ] 16 return lista 17 18 # Uso : 19 datos = [29 , 10 , 14 , 37 , 13] 20 print ( seleccion_inplace ( datos. copy () ) )
1 class Nodo : 2 def init ( self , valor ) : 3 self. valor = valor 4 self. siguiente = None 5 6 def burbuja_lista_enlazada ( cabeza ) : 7 if not cabeza : 8 return None 9 10 cambiado = True 11 while cambiado : 12 cambiado = False 13 actual = cabeza 14 while actual. siguiente : 15 if actual. valor > actual. siguiente. valor : 16 # Intercambio de valores sin cambiar nodos 17 actual. valor , actual. siguiente. valor = actual. siguiente. valor , actual. valor 18 cambiado = True 19 actual = actual. siguiente 20 return cabeza 21 22 # Uso : 23 def imprimir_lista ( nodo ) : 24 while nodo : 25 print ( nodo. valor , end = " -> " ) 26 nodo = nodo. siguiente 27 print ( " None " ) 28 29 # Crear lista : 4 -> 2 -> 1 -> 3 30 n1 , n2 , n3 , n4 = Nodo (4) , Nodo (2) , Nodo (1) , Nodo (3) 31 n1. siguiente , n2. siguiente , n3. siguiente = n2 , n3 , n 32 ordenada = burbuja_lista_enlazada ( n1 ) 33 imprimir_lista ( ordenada ) # 1 -> 2 -> 3 -> 4 -> None
1 def busqueda_funcion ( func , objetivo , low , high , precision =1 e -6) : 2 while high - low > precision : 3 mid = ( low + high ) / 2 4 if func ( mid ) < objetivo : 5 low = mid 6 else : 7 high = mid 8 return ( low + high ) / 2 9 10 # Ejemplo : encontrar x donde x ^2 = 2 ( r a z de 2) 11 print ( busqueda_funcion ( lambda x : x *x , 2 , 0 , 2) ) # 1.
1 def seleccion_dyv ( lista ) : 2 if len ( lista ) <= 1: 3 return lista 4 5 pivot = lista [ len ( lista ) //2]