1. 简介
回文串是指正读和反读都相同的单词、短语、数字或字符序列。✅ 换句话说,字符串反转后仍与原串一致。例如 "racecar"
就是一个典型的回文串——无论从左到右还是从右到左读,结果都一样。
本文将介绍在 Kotlin 中判断字符串是否为回文串的几种常用方法。这些方法各有特点,在实际开发中可根据场景灵活选择,避免踩坑 ❌。
2. 测试用例设计
为了验证每种方法的正确性,我们准备以下测试数据:
✅ 是回文串:
racecar
redivider
3553
tattarrattat
❌ 非回文串:
palindrome
sever
这些用例覆盖了常见字母组合和数字,有助于全面检验算法逻辑。
3. 使用循环判断
最直观的方法是使用双指针技术(two-pointer technique),从字符串两端向中间逐对比较字符。
fun isPalindrome(str: String): Boolean {
var start = 0
var end = str.length - 1
while (start < end) {
if (str[start] != str[end]) {
return false
}
start++
end--
}
return true
}
📌 核心思路:
- 初始化两个索引:
start
指向开头,end
指向末尾 - 当
start < end
时持续比较对应位置字符 - 一旦发现不匹配立即返回
false
- 成功遍历到中间则说明是回文串
测试代码如下:
@Test
fun `palindrome check using loop function`(){
assertTrue(isPalindrome("racecar"))
assertTrue(isPalindrome("redivider"))
assertFalse(isPalindrome("palindrome"))
assertFalse(isPalindrome("sever"))
assertTrue(isPalindrome("3553"))
assertTrue(isPalindrome("tattarrattat"))
}
⚠️ 注意:此方法时间复杂度为 O(n/2),空间复杂度为 O(1),效率高且无需额外存储,适合处理大字符串。
4. 使用 reversed() 内置函数
Kotlin 提供了简洁的字符串反转 API —— reversed()
,我们可以直接利用它进行对比。
fun isPalindromeWithBuiltInFunction(str: String): Boolean {
val reversedStr = str.reversed()
return str == reversedStr
}
📌 特点分析:
- ✅ 代码极其简洁,可读性强
- ❌ 需要创建新的字符串对象,内存开销为 O(n)
- ⚠️ 在性能敏感场景下需谨慎使用,尤其是长字符串
对应的单元测试:
@Test
fun `palindrome check using built in function`(){
assertTrue(isPalindromeWithBuiltInFunction("racecar"))
assertTrue(isPalindromeWithBuiltInFunction("redivider"))
assertFalse(isPalindromeWithBuiltInFunction("palindrome"))
assertFalse(isPalindromeWithBuiltInFunction("sever"))
assertTrue(isPalindromeWithBuiltInFunction("3553"))
assertTrue(isPalindromeWithBuiltInFunction("tattarrattat"))
}
💡 小贴士:虽然写起来爽,但在高频调用或大数据量场景下,这种“一行流”写法可能成为性能瓶颈。
5. 使用递归实现
递归方式通过不断缩小问题规模来求解:每次比较首尾字符,然后对去掉首尾后的子串继续判断。
fun isPalindromeUsingRecursion(str: String): Boolean {
if (str.length <= 1) {
return true
}
if (str.first() != str.last()) {
return false
}
return isPalindromeUsingRecursion(str.substring(1, str.length - 1))
}
📌 执行流程:
- 终止条件:空串或单字符 → 返回
true
- 比较首尾字符 → 不同则返回
false
- 否则递归处理子串
[1..length-2]
测试用例:
@Test fun `palindrome check using recursion`(){
assertTrue(isPalindromeUsingRecursion("racecar"))
assertTrue(isPalindromeUsingRecursion("redivider"))
assertFalse(isPalindromeUsingRecursion("palindrome"))
assertFalse(isPalindromeUsingRecursion("sever"))
assertTrue(isPalindromeUsingRecursion("3553"))
assertTrue(isPalindromeUsingRecursion("tattarrattat"))
}
⚠️ 警告:该方法存在明显缺陷:
- 每次递归都会创建新字符串(
substring
) - 调用栈深度可达 n/2,极端情况下可能引发
StackOverflowError
- 时间和空间复杂度均为 O(n),不推荐用于生产环境
6. 总结
本文系统梳理了 Kotlin 中判断回文串的三种主流方法:
方法 | 时间复杂度 | 空间复杂度 | 优点 | 缺点 |
---|---|---|---|---|
循环双指针 | O(n) | O(1) | 高效、稳定 | 略显冗长 |
reversed() |
O(n) | O(n) | 简洁易懂 | 占用额外内存 |
递归 | O(n) | O(n) | 逻辑清晰 | 易栈溢出 |
✅ 推荐实践:
- 日常开发首选循环法,兼顾性能与可维护性
- 快速原型或脚本场景可用
reversed()
写法提升开发效率 - 递归仅作学习理解之用,慎用于线上服务
所有示例代码及完整测试用例已托管至 GitHub:https://github.com/Baeldung/kotlin-tutorials/tree/master/core-kotlin-modules/core-kotlin-strings-3