Post

Strings: Valid Palindrome — Kotlin Solution

Strings: Valid Palindrome — Kotlin Solution

Problem Info

  
LeetCode #125 — Valid Palindrome
DifficultyEasy
TopicStrings, 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, return true if it is a palindrome, or false otherwise.

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:

  1. Clean the string — keep only alphanumeric characters, lowercase everything
  2. 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

ApproachTimeSpaceNotes
Clean + reverseO(n)O(n)Most readable — Kotlin one-liner
Two pointersO(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)

  
TimeO(n) — each character visited at most once
SpaceO(1) — no extra string created

Key Takeaway

Skip non-alphanumeric, compare from both ends toward the middle. Kotlin’s isLetterOrDigit() and lowercaseChar() make this cleaner than Java without any regex.

🔗 Solve it on LeetCode →


📚 Kotlin DSA Series

This post is part of the Kotlin DSA series — solving LeetCode problems using idiomatic Kotlin.

← View Full Series Index
This post is licensed under CC BY 4.0 by the author.