Strings: Valid Palindrome — Kotlin Solution
Problem Info
| LeetCode # | 125 — Valid Palindrome |
| Difficulty | Easy |
| Topic | Strings, Two Pointers |
A phrase is a palindrome if, after converting all uppercase letters to lowercase and removing all non-alphanumeric characters, it reads the same forward and backward.
Given a string
s, returntrueif it is a palindrome, orfalseotherwise.
Example:
1
2
3
4
5
Input: s = "A man, a plan, a canal: Panama"
Output: true // "amanaplanacanalpanama"
Input: s = "race a car"
Output: false // "raceacar"
Approach
Two steps:
- Clean the string — keep only alphanumeric characters, lowercase everything
- Check if it reads the same forward and backward
Approach 1 — Clean then reverse: Filter, then compare with reversed version.
Approach 2 — Two pointers (O(1) space): Left pointer starts at beginning, right at end. Skip non-alphanumeric characters, compare characters at both pointers. If any mismatch — not a palindrome.
Kotlin Solution
Approach 1 — Clean and Reverse (simple)
1
2
3
4
fun isPalindrome(s: String): Boolean {
val cleaned = s.filter { it.isLetterOrDigit() }.lowercase()
return cleaned == cleaned.reversed()
}
Approach 2 — Two Pointers (optimal)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
fun isPalindrome(s: String): Boolean {
var left = 0
var right = s.length - 1
while (left < right) {
while (left < right && !s[left].isLetterOrDigit()) left++
while (left < right && !s[right].isLetterOrDigit()) right--
if (s[left].lowercaseChar() != s[right].lowercaseChar()) return false
left++
right--
}
return true
}
Why Kotlin Shines Here
filter { it.isLetterOrDigit() } — built-in alphanumeric check, no regex needed:
1
2
s.filter { it.isLetterOrDigit() }.lowercase()
// vs Java: s.replaceAll("[^a-zA-Z0-9]", "").toLowerCase()
.reversed() — string reversal as a direct extension function:
1
2
cleaned == cleaned.reversed()
// vs Java: cleaned.equals(new StringBuilder(cleaned).reverse().toString())
lowercaseChar() — per-character lowercase without converting the whole string:
1
2
s[left].lowercaseChar() != s[right].lowercaseChar()
// vs Java: Character.toLowerCase(s.charAt(left))
Two Approaches Compared
| Approach | Time | Space | Notes |
|---|---|---|---|
| Clean + reverse | O(n) | O(n) | Most readable — Kotlin one-liner |
| Two pointers | O(n) | O(1) | No extra string allocation |
Both are O(n) time. The two pointer approach is preferred in interviews for O(1) space. The clean + reverse approach is what you’d write in production Kotlin for readability.
Complexity (Two Pointers)
| Time | O(n) — each character visited at most once |
| Space | O(1) — no extra string created |
Key Takeaway
Skip non-alphanumeric, compare from both ends toward the middle. Kotlin’s
isLetterOrDigit()andlowercaseChar()make this cleaner than Java without any regex.
This post is part of the Kotlin DSA series — solving LeetCode problems using idiomatic Kotlin.
← View Full Series Index