Swift en LeetCode: por dónde empezar y cómo no rendirse
Todo desarrollador iOS, tarde o temprano, se topa con una pared: haces proyectos, envías aplicaciones a la AppStore, pero en la entrevista te dan un problema sobre un árbol binario y te quedas en blanco. ¿Te suena? LeetCode es ese entrenador que transforma un «solo sé escribir UI» en «pienso en algoritmos». Pero hay un detalle: la mayoría de las soluciones en internet están escritas en Python o Java, y Swift es un lenguaje con su propia filosofía. En este artículo, analizaremos cómo resolver problemas de LeetCode eficazmente en Swift, qué estructuras de datos usar y en qué fijarte para no perder tiempo.
Este artículo es para quienes ya conocen los fundamentos de Swift, pero quieren mejorar su pensamiento algorítmico. No enseñaremos sintaxis, aprenderemos a pensar.
Por qué Swift es una excelente opción para LeetCode
Muchos piensan que Swift es solo UIKit y SwiftUI, pero en realidad el lenguaje ofrece potentes capacidades para problemas algorítmicos:
- Tipos opcionales — trabajo seguro con nil sin crashes inesperados.
- Value types (estructuras) — copia predecible, sin sorpresas con referencias.
- Cálculo diferido y enfoques funcionales — map, filter, reduce simplifican mucho el código.
- Velocidad — Swift se compila a código nativo, a menudo superando a Python en 2-3 veces.
Sin embargo, también hay trampas: por ejemplo, los arrays en Swift son estructuras, y copiar un array grande puede ser costoso. Pero hablaremos de eso por separado.
Estructuras de datos: lo que necesitas saber para Swift en LeetCode
Antes de lanzarte a resolver problemas, asegúrate de manejar con soltura las estructuras básicas. Aquí tienes una lista de must-know para Swift:
Arrays y slices (Array, ArraySlice)
Los arrays en Swift no son solo listas, sino estructuras potentes con acceso O(1) por índice. Pero cuidado: insertar/eliminar al principio es O(n). Usa ArraySlice para no copiar datos al trabajar con subarrays.
let numbers = [1, 2, 3, 4, 5]let slice = numbers[1..<4] // ArraySlice, sin copiaprint(slice) // [2, 3, 4]Diccionarios y conjuntos (Dictionary, Set)
Para problemas de conteo de frecuencias, búsqueda de duplicados o algoritmos de dos pasadas, son tus mejores amigos. Recuerda: Dictionary es una tabla hash, O(1) en promedio, pero puede degradarse a O(n) con una mala función hash.
func twoSum(_ nums: [Int], _ target: Int) -> [Int] { var dict = [Int: Int]() for (i, num) in nums.enumerated() { if let j = dict[target - num] { return [j, i] } dict[num] = i } return []}Pila y cola (Stack, Queue)
En Swift no hay estructuras de pila y cola incorporadas, pero se pueden emular fácilmente con un array. Para la pila: append y popLast. Para la cola, usa ArraySlice o una lista doblemente enlazada para evitar O(n) en dequeue.
struct Stack<T> { private var array = [T]() mutating func push(_ element: T) { array.append(element) } mutating func pop() -> T? { array.popLast() } var isEmpty: Bool { array.isEmpty }}Listas enlazadas (Linked List)
A LeetCode le encantan los problemas con listas simplemente enlazadas. En Swift no hay una implementación incorporada, pero puedes definir una clase:
class ListNode { var val: Int var next: ListNode? init(_ val: Int) { self.val = val; self.next = nil }}Esto es un clásico para problemas de invertir una lista, detectar ciclos o eliminar un nodo.
Patrones algorítmicos para problemas en Swift
Para no reinventar la rueda cada vez, memoriza algunos patrones que cubren el 80% de los problemas de LeetCode.
Dos punteros (Two Pointers)
E