Swift vs Kotlin for Coding Interviews: The Library Gap Is Real

- Kotlin runs on the JVM and inherits the full Java collections framework, including
PriorityQueue,TreeMap, andArrayDeque, out of the box - Swift's standard library ships only
Array,Dictionary, andSet; theswift-collectionsHeapis unavailable on LeetCode, so you implement one from scratch - BFS in Swift requires a head-pointer workaround because
removeFirst()is O(n), adding linear cost to every level of traversal - Swift integers trap on overflow at runtime;
lo + (hi - lo) / 2is non-optional for binary search midpoints - Swift arrays are value types with copy-on-write, which eliminates the Python backtracking snapshot bug automatically
- Kotlin's
tailreckeyword converts eligible tail-recursive functions to loops, preventing stack overflow with no code restructuring - Fluency beats features: if you know Swift well and Kotlin poorly, implement the heap from scratch; fumbling with unfamiliar syntax costs more than a missing built-in
You know Swift. Or you know Kotlin. Your Python is passable but not exactly fluent. You've been staring at this language-selection screen on LeetCode for ten minutes and honestly, it's starting to feel like a personality test you weren't told about.
The short answer: use the language you actually know. Fluency beats prestige every time. But the decision is not symmetric. Pick without knowing the tradeoffs and you'll hit surprises mid-interview that have nothing to do with the algorithm.
Kotlin has a structural advantage in algorithmic interviews because it runs on the JVM and inherits the entire Java standard library. Swift is a great language built for great things. Those things are mostly app development, not the particular data structures that show up in 45-minute coding problems on a Tuesday.
Both Are Officially Supported, But That's Only Half the Story
LeetCode and CoderPad both support Swift and Kotlin. You will not be fighting the platform in either language.
The gap is not about support. It's about what ships in the box. Kotlin runs on the JVM, so you get java.util.PriorityQueue, java.util.TreeMap, java.util.ArrayDeque, and the full Java collections framework. Swift gives you Array, Dictionary, Set, and not much else. Apple's swift-collections package adds Heap and Deque, but LeetCode's Swift environment does not include it. Candidates have been asking for years.
For easy and medium problems this rarely matters. For anything involving a priority queue, sorted map, or efficient double-ended queue, it matters a lot.
The Collections Gap Is Wider Than You Think
Suppose a problem needs a min-heap. This comes up constantly: top-K elements, Dijkstra's, merge K sorted lists.
In Kotlin:
import java.util.PriorityQueue val minHeap = PriorityQueue<Int>() // min-heap by default val maxHeap = PriorityQueue<Int>(reverseOrder()) // max-heap val byFirst = PriorityQueue<IntArray>(compareBy { it[0] }) // custom comparator
In Swift:
// No PriorityQueue in the standard library. // swift-collections has Heap, but it's not on LeetCode. // You implement a binary heap from scratch. struct MinHeap { var data: [Int] = [] mutating func push(_ val: Int) { ... } // ~15 lines mutating func pop() -> Int { ... } // ~15 lines func peek() -> Int? { data.first } }
Not the end of the world. A binary heap takes about 25-30 lines and runs correctly once you've written it a few times. But those are 25-30 lines under time pressure, and a bug in your heap is hard to distinguish from a bug in your algorithm.

Debugging your hand-rolled Swift heap while the interviewer watches the clock
Sorted maps hit equally hard. Kotlin has TreeMap:
val map = TreeMap<Int, Int>() map[3] = "three" map.floorKey(5) // largest key <= 5 map.ceilingKey(5) // smallest key >= 5 map.firstKey() // minimum key map.lastKey() // maximum key
Swift has no sorted map in the standard library. You'd need a sorted array plus binary search, which is several more lines and another source of off-by-one errors.
This is the core tradeoff: Kotlin's access to Java's collections lets you spend 45 minutes on the algorithm. Swift's leaner standard library sometimes requires spending part of that time rebuilding infrastructure.
Quick reference:
| Need | Kotlin | Swift |
|---|---|---|
| Min or max heap | PriorityQueue (built-in) | Implement from scratch |
| Sorted map with floor/ceiling | TreeMap (built-in) | Not available |
| Sorted set | TreeSet (built-in) | Not available |
| O(1) deque for BFS | ArrayDeque (built-in) | Array.removeFirst() is O(n) |
| Tail call optimization | tailrec keyword | Not available |
The deque point deserves a callout. Swift arrays support append (O(1)) and removeLast (O(1)) for stack operations. But removeFirst() is O(n), meaning a naive BFS queue adds a linear factor to every level of your traversal. Fix it with a head pointer:
var queue = [startNode] var head = 0 while head < queue.count { let node = queue[head] head += 1 // process node... }
It works, but it's one more thing to remember. The Swift for Coding Interviews guide covers the full collections breakdown in detail.
Swift Will Crash Where Java Just Wraps
Beyond data structures, Swift has a few behaviors that catch people who learned on Python or Java.
Integer overflow crashes your program. Swift traps on overflow at runtime rather than wrapping silently. The classic binary search midpoint will get you:
let mid = (lo + hi) / 2 // crashes if lo + hi > Int.max let mid = lo + (hi - lo) / 2 // correct
Kotlin and Java inherit JVM overflow behavior, where integers wrap silently. That's also wrong in theory, but it won't blow up your solution. See the integer overflow guide for how this plays out across languages.
Swift arrays are value types, which is actually a feature. Swift arrays are structs. Assigning or passing them creates a copy via copy-on-write. This eliminates the classic Python backtracking bug where you append a reference to a mutable list instead of a snapshot:
# Python: this is wrong, all entries point to the same list result.append(path) # correct result.append(path[:])
// Swift: this is correct, path is copied automatically result.append(path)
One bug class simply disappears. Know the semantics so you're not surprised when mutating a "copy" doesn't affect the original.
Numeric types don't mix without explicit conversion. Int and UInt won't combine without a cast. Array count returns Int in Swift. Keep everything Int unless you have a specific reason not to.
What Kotlin Gets Right
The Java standard library access is the headline, but Kotlin's own syntax adds a few wins.
tailrec prevents stack overflow for eligible functions. Mark a tail-recursive function with tailrec and the Kotlin compiler transforms it into a loop. No stack overflow risk, same readable code:
tailrec fun gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b)
Swift has no equivalent. Recurse deep enough and you'll hit a stack overflow.
Multi-key sorting is cleaner. Kotlin's compareBy and thenBy compose well for problems that need custom sort orders:
// sort by string length, then alphabetically words.sortedWith(compareBy({ it.length }, { it }))
Swift requires a manual comparison closure:
words.sorted { a, b in a.count != b.count ? a.count < b.count : a < b }
Both work. Kotlin's version is less error-prone under pressure.
Destructuring is handy for pairs and data classes:
val pairs = listOf(1 to 2, 3 to 4) for ((a, b) in pairs) { println("$a $b") }
Swift doesn't have destructuring for arbitrary types, though tuples work for simple cases.
For the full Kotlin picture, the Kotlin for Coding Interviews guide has the collections decision table and the traps that parallel the ones in Java for Coding Interviews.
The Surface Differences Are Minor
Both languages are concise enough for interviews. The differences here are cosmetic.
Default value when a key is missing:
// Kotlin map.getOrDefault("key", 0) map.getOrElse("key") { 0 }
// Swift map["key", default: 0]
Swift wins this one. The subscript default syntax is genuinely clean.
String interpolation:
println("size is ${list.size}")
print("size is \(list.count)")
Neither is a footgun. Just different.
Null and nil safety follow the same philosophy in both languages. Kotlin uses ? for nullable types and !! to force unwrap (crashes on nil). Swift uses Optional and ! (also crashes on nil). The mental model is identical.
Does Raw Speed Matter?
Not really. LeetCode time limits are set to pass correct algorithmic solutions, not to discriminate between languages. Both Kotlin (JVM with JIT) and Swift (compiled to native) are fast enough. You will not time-out on a correct O(n log n) solution in either language.
The JVM cold start adds a small overhead on the first run, which occasionally shows up in LeetCode benchmarks but never causes a "Time Limit Exceeded" on a correctly implemented algorithm. Don't let this be the thing you lose sleep over.
Which Should You Pick for a Coding Interview?
Interviewing for iOS roles at Apple, Airbnb, Lyft, or any company with a mobile team: use Swift. The interviewer likely knows it. Using your native platform language signals real fluency rather than someone who learned a language to pass a test. Know the heap gap and the overflow behavior, and you'll be fine for most problems.
Interviewing for Android roles or general backend positions: Kotlin is the natural choice. The Java library access makes it a stronger algorithmic tool, and you get the expressiveness of Kotlin on top.
Choosing purely for general SWE interviews with no mobile context: Kotlin has a real edge. Not because Swift is weak but because java.util.PriorityQueue and java.util.TreeMap show up often enough that their absence becomes recurring friction.
If you're truly fluent in one and shaky in the other: use the one you know. Fumbling with unfamiliar syntax is more expensive than implementing a heap from scratch in your native language. The best language for coding interviews guide makes this case in full.
Whatever you choose, practice narrating your solution out loud. The data structure gap only hurts you if you freeze on the implementation. SpaceComplexity runs voice-based mock interviews with rubric-based feedback covering both what you code and how you explain it. A few sessions before your real loop will tell you exactly where you're losing points.