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.
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!"
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
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:
- Tamaño fijo: El tamaño de ventana es constante
- 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
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
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:
- ✅ Dos Punteros - Pares y tripletas
- ✅ Ventana Deslizante - Subarrays y substrings
- ✅ Punteros Rápido y Lento - Ciclos y elementos del medio
- ✅ Merge Intervals - Rangos superpuestos
- ✅ Cyclic Sort - Números en rango dado
- ✅ Reversión In-place - Reversión de LinkedList
- ✅ Tree BFS - Recorrido por niveles
- ✅ Tree DFS - Problemas de caminos
- ✅ Two Heaps - Encontrar mediana
- ✅ 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: