Domina 10 Patrones Esenciales de Algoritmos para Entrevistas de Programación
Entrevistas Técnicas15 min lectura

Domina 10 Patrones Esenciales de Algoritmos para Entrevistas de Programación

👤
Interview Whisper Team
1 de noviembre de 2025

La mayoría de los candidatos abordan las entrevistas de programación de manera incorrecta.

Memorizan cientos de problemas individuales. Haciendo grinding en LeetCode, tratando de cubrir cada posible pregunta.

Pero aquí está el secreto que conocen los mejores: La mayoría de los problemas de programación siguen patrones reconocibles.

Domina estos 10 patrones, y podrás resolver 80% de las preguntas de entrevista—incluso las que nunca has visto.

En lugar de memorizar 500 problemas, entenderás los conceptos fundamentales que desbloquean miles de variaciones.

Es la diferencia entre memorizar respuestas y entender cómo pensar.

Patrones de algoritmos y estructuras de datos

Por Qué Importan los Patrones

Piensa en los patrones de algoritmos como las aperturas de ajedrez.

No memorizas cada posible partida de ajedrez—aprendes patrones estratégicos que aplican a miles de partidas.

El mismo principio aplica a las entrevistas de programación.

Cuando ves un nuevo problema, el reconocimiento de patrones te ayuda a identificar inmediatamente el enfoque. "Esto parece un problema de ventana deslizante," piensas, y de repente sabes exactamente por dónde empezar.

No más miradas en blanco. No más pánico.

Beneficios del aprendizaje basado en patrones:

Resuelve nuevos problemas más rápido

En lugar de quedarte en blanco ante un problema desconocido, reconocerás el patrón subyacente y aplicarás la plantilla que has practicado.

Reconoce variaciones de problemas conocidos

La mayoría de las preguntas "nuevas" de entrevista son solo variaciones de problemas clásicos. Los patrones te ayudan a ver a través del disfraz.

Construye intuición real para resolver problemas

Con patrones, desarrollas un sexto sentido para qué enfoque funcionará mejor—incluso antes de empezar a codificar.

Reduce el estrés de la entrevista

No hay nada más tranquilizador que pensar, "¡He resuelto problemas como este antes!"

Técnica de dos punteros

Patrón #1: Dos Punteros

El patrón de dos punteros es una de las técnicas más elegantes. Usa dos puntos de referencia que se mueven a través de la estructura de datos para encontrar relaciones o satisfacer condiciones.

Cuándo usar: Problemas que involucran arrays, strings o listas enlazadas donde necesitas encontrar pares, tripletas o subarrays.

Indicadores clave:

"Encuentra par que suma X" - Dos punteros clásicos desde ambos extremos de un array ordenado.

"Elimina duplicados en array ordenado" - Un puntero lee, otro escribe valores únicos.

"Invierte un string" - Los punteros empiezan en extremos opuestos e intercambian hacia adentro.

Estructura básica:

def dos_punteros_template(arr):
    izq = 0
    der = len(arr) - 1

    while izq < der:
        # Calcular algo con arr[izq] y arr[der]
        if condicion_cumplida:
            return resultado
        elif izq_debe_moverse:
            izq += 1
        else:
            der -= 1

    return resultado

Ejemplo: Two Sum (array ordenado)

def two_sum_sorted(numbers, target):
    """
    Encuentra dos números que suman el target en array ordenado.
    Tiempo: O(n), Espacio: O(1)
    """
    izq, der = 0, len(numbers) - 1

    while izq < der:
        suma_actual = numbers[izq] + numbers[der]

        if suma_actual == target:
            return [izq, der]
        elif suma_actual < target:
            izq += 1  # Necesita suma mayor
        else:
            der -= 1  # Necesita suma menor

    return []

# Test
print(two_sum_sorted([1, 2, 3, 4, 6], 6))  # [1, 3] → 2+4=6

Más problemas para practicar:

  • 3Sum
  • Remove Nth Node From End
  • Trapping Rain Water
  • Valid Palindrome

Técnica de ventana deslizante

Patrón #2: Ventana Deslizante

El patrón de ventana deslizante es perfecto para problemas que involucran secuencias contiguas. Imagina una ventana deslizándose a través de tu array o string, expandiéndose y contrayéndose según sea necesario.

Cuándo usar: Problemas que involucran subarrays o substrings con condiciones específicas.

Indicadores clave:

"Substring más largo/corto con..." - La ventana se expande para encontrar el más largo, se contrae para el más corto.

"Suma máxima de subarray de tamaño K" - Ventana de tamaño fijo se desliza para encontrar suma máxima.

"Encuentra todos los anagramas" - La ventana rastrea frecuencia de caracteres para coincidir patrones.

Dos tipos:

  1. Tamaño fijo: El tamaño de ventana es constante
  2. Tamaño dinámico: La ventana crece y encoge

Template ventana fija:

def ventana_fija(arr, k):
    suma_ventana = sum(arr[:k])
    suma_max = suma_ventana

    for i in range(k, len(arr)):
        # Desliza la ventana
        suma_ventana = suma_ventana - arr[i - k] + arr[i]
        suma_max = max(suma_max, suma_ventana)

    return suma_max

Template ventana dinámica:

def ventana_dinamica(s, condicion):
    izq = 0
    resultado = float('inf')
    estado_actual = {}

    for der in range(len(s)):
        # Expande ventana incluyendo s[der]
        # Actualiza estado_actual

        while condicion_cumplida:
            # Actualiza resultado si es necesario
            # Contrae ventana desde izquierda
            izq += 1

    return resultado

Ejemplo: Longest Substring Without Repeating Characters

def length_of_longest_substring(s):
    """
    Encuentra longitud del substring más largo sin caracteres repetidos.
    Tiempo: O(n), Espacio: O(min(n, m)) donde m es tamaño charset
    """
    char_set = set()
    izq = 0
    max_length = 0

    for der in range(len(s)):
        # Contrae ventana hasta no haber duplicados
        while s[der] in char_set:
            char_set.remove(s[izq])
            izq += 1

        # Añade caracter actual
        char_set.add(s[der])
        max_length = max(max_length, der - izq + 1)

    return max_length

# Test
print(length_of_longest_substring("abcabcbb"))  # 3 (abc)

Patrón #3: Punteros Rápido y Lento

Cuándo usar: Problemas que involucran ciclos o encontrar elementos del medio en listas enlazadas.

Indicadores clave:

  • "Detectar ciclo"
  • "Encontrar elemento del medio"
  • "Happy number"
  • "Inicio del ciclo"

Template:

def punteros_rapido_lento(head):
    lento = head
    rapido = head

    while rapido and rapido.next:
        lento = lento.next        # Mueve 1 paso
        rapido = rapido.next.next # Mueve 2 pasos

        if lento == rapido:
            return True  # Ciclo detectado

    return False  # Sin ciclo

Ejemplo: Linked List Cycle

def has_cycle(head):
    """
    Detecta si lista enlazada tiene ciclo.
    Tiempo: O(n), Espacio: O(1)
    """
    if not head or not head.next:
        return False

    lento = head
    rapido = head

    while rapido and rapido.next:
        lento = lento.next
        rapido = rapido.next.next

        if lento == rapido:
            return True

    return False

Patrón #4: Merge Intervals

Cuándo usar: Problemas con intervalos superpuestos o rangos.

Indicadores clave:

  • "Merge overlapping intervals"
  • "Insert interval"
  • "Meeting rooms"
  • "Citas conflictivas"

Template:

def merge_intervals(intervals):
    if not intervals:
        return []

    # Ordena por tiempo de inicio
    intervals.sort(key=lambda x: x[0])
    merged = [intervals[0]]

    for current in intervals[1:]:
        last = merged[-1]

        if current[0] <= last[1]:  # Superpuestos
            # Merge actualizando tiempo final
            last[1] = max(last[1], current[1])
        else:
            merged.append(current)

    return merged

Patrón #5: Cyclic Sort

Cuándo usar: Problemas con arrays que contienen números en un rango dado.

Indicadores clave:

  • "Encuentra número faltante en rango [1, n]"
  • "Encuentra número duplicado"
  • Números en rango [0, n] o [1, n]

Template:

def cyclic_sort(nums):
    i = 0
    while i < len(nums):
        correct_index = nums[i] - 1  # Para rango [1, n]

        if nums[i] != nums[correct_index]:
            # Intercambia a posición correcta
            nums[i], nums[correct_index] = nums[correct_index], nums[i]
        else:
            i += 1

    return nums

Patrón #6: Reversión In-place de LinkedList

Cuándo usar: Problemas que requieren reversión de listas enlazadas.

Indicadores clave:

  • "Invierte una lista enlazada"
  • "Invierte cada K-elementos"
  • "Rota una lista enlazada"

Template:

def reverse_linked_list(head):
    prev = None
    current = head

    while current:
        next_node = current.next  # Guarda siguiente
        current.next = prev       # Invierte enlace
        prev = current            # Mueve prev adelante
        current = next_node       # Mueve current adelante

    return prev  # Nueva cabeza

Algoritmos de árboles

Patrón #7: Tree BFS (Búsqueda en Anchura)

La Búsqueda en Anchura explora un árbol nivel por nivel, como ondas expandiéndose en el agua.

Cuándo usar: Problemas que requieren recorrido por niveles de árboles.

Indicadores clave:

"Recorrido por niveles" - Visita nodos nivel por nivel de arriba hacia abajo.

"Recorrido zigzag" - Alterna dirección para cada nivel.

"Profundidad mínima" - BFS encuentra el camino más corto a una hoja eficientemente.

Template:

from collections import deque

def level_order_traversal(root):
    if not root:
        return []

    resultado = []
    cola = deque([root])

    while cola:
        tamano_nivel = len(cola)
        nivel_actual = []

        for _ in range(tamano_nivel):
            nodo = cola.popleft()
            nivel_actual.append(nodo.val)

            if nodo.left:
                cola.append(nodo.left)
            if nodo.right:
                cola.append(nodo.right)

        resultado.append(nivel_actual)

    return resultado

Patrón #8: Tree DFS (Búsqueda en Profundidad)

Cuándo usar: Problemas de árboles que requieren recorrido de caminos.

Indicadores clave:

  • "Suma de camino"
  • "Todos los caminos"
  • "Diámetro del árbol"
  • "Profundidad máxima"

Tres tipos de recorrido:

def inorder(root):     # Izq, Raíz, Der
    if not root:
        return []
    return inorder(root.left) + [root.val] + inorder(root.right)

def preorder(root):    # Raíz, Izq, Der
    if not root:
        return []
    return [root.val] + preorder(root.left) + preorder(root.right)

def postorder(root):   # Izq, Der, Raíz
    if not root:
        return []
    return postorder(root.left) + postorder(root.right) + [root.val]

Patrón #9: Two Heaps

Cuándo usar: Problemas que involucran encontrar medianas o scheduling.

Indicadores clave:

  • "Encuentra mediana"
  • "Mediana de ventana deslizante"
  • "Maximizar capital"

Template:

import heapq

class MedianFinder:
    def __init__(self):
        self.small = []  # Max heap (invertir valores)
        self.large = []  # Min heap

    def add_num(self, num):
        # Añade a max heap (small)
        heapq.heappush(self.small, -num)

        # Balancea: mueve más grande de small a large
        heapq.heappush(self.large, -heapq.heappop(self.small))

        # Si large tiene más elementos, rebalancea
        if len(self.large) > len(self.small):
            heapq.heappush(self.small, -heapq.heappop(self.large))

    def find_median(self):
        if len(self.small) > len(self.large):
            return -self.small[0]
        return (-self.small[0] + self.large[0]) / 2.0

Patrón #10: Búsqueda Binaria Modificada

Cuándo usar: Arrays ordenados o rotados, encontrar rangos.

Indicadores clave:

  • "Buscar en array ordenado"
  • "Encontrar punto de rotación"
  • "Buscar en array rotado"

Template:

def binary_search(arr, target):
    izq, der = 0, len(arr) - 1

    while izq <= der:
        mid = izq + (der - izq) // 2

        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            izq = mid + 1
        else:
            der = mid - 1

    return -1

Ejemplo: Search in Rotated Array

def search_rotated(nums, target):
    """
    Busca en array ordenado rotado.
    Tiempo: O(log n), Espacio: O(1)
    """
    izq, der = 0, len(nums) - 1

    while izq <= der:
        mid = izq + (der - izq) // 2

        if nums[mid] == target:
            return mid

        # Determina qué mitad está ordenada
        if nums[izq] <= nums[mid]:
            # Mitad izquierda ordenada
            if nums[izq] <= target < nums[mid]:
                der = mid - 1
            else:
                izq = mid + 1
        else:
            # Mitad derecha ordenada
            if nums[mid] < target <= nums[der]:
                izq = mid + 1
            else:
                der = mid - 1

    return -1

Práctica y dominio de patrones de algoritmos

Cómo Practicar Estos Patrones

Semana 1-2: Aprende los Patrones

Estudia un patrón por día. Profundiza en la mecánica del patrón, cuándo usarlo y variaciones comunes.

Entiende la plantilla. No solo copies código—entiende por qué existe cada línea.

Resuelve 2-3 problemas fáciles por patrón. Aplica la plantilla a problemas simples hasta que se sienta natural.

Semana 3-4: Practica Variaciones

  • Resuelve problemas medios
  • Mezcla patrones (algunos problemas usan múltiples)
  • Cronométrate

Semana 5-6: Domina Problemas Avanzados

  • Aborda problemas difíciles
  • Haz entrevistas de práctica
  • Revisa y optimiza soluciones

Cheatsheet de Reconocimiento de Patrones

Si el problema menciona... Considera patrón...
Array/string ordenado Dos Punteros, Búsqueda Binaria
Pares/tripletas Dos Punteros
Subarray/substring Ventana Deslizante
Ciclo en lista enlazada Punteros Rápido y Lento
Intervalos superpuestos Merge Intervals
Números en rango [1,n] Cyclic Sort
Invertir lista enlazada Reversión In-place
Árbol por niveles BFS
Caminos en árbol DFS
Encontrar mediana Two Heaps
Buscar en ordenado Búsqueda Binaria

Conclusión

En lugar de memorizar 500 problemas individuales, domina estos 10 patrones:

  1. ✅ Dos Punteros - Pares y tripletas
  2. ✅ Ventana Deslizante - Subarrays y substrings
  3. ✅ Punteros Rápido y Lento - Ciclos y elementos del medio
  4. ✅ Merge Intervals - Rangos superpuestos
  5. ✅ Cyclic Sort - Números en rango dado
  6. ✅ Reversión In-place - Reversión de LinkedList
  7. ✅ Tree BFS - Recorrido por niveles
  8. ✅ Tree DFS - Problemas de caminos
  9. ✅ Two Heaps - Encontrar mediana
  10. ✅ Búsqueda Binaria Modificada - Arrays ordenados

Con estos patrones, reconocerás el enfoque para la mayoría de los problemas en segundos.

¿Listo para practicar con guía de IA? Descarga Interview Whisper y obtén ayuda en tiempo real para reconocimiento de patrones durante tu práctica de programación.


Artículos Relacionados:

#patrones de algoritmos#entrevista de programación#estructuras de datos#patrones leetcode#entrevista técnica#dos punteros#ventana deslizante#programación dinámica

Found this helpful? Share it!

¿Listo para tu próxima entrevista?

Obtén coaching de IA en tiempo real durante tus entrevistas

Descargar Gratis