回文数判断是算法学习中的经典入门题目,也是各大技术面试中的高频考点。所谓回文数,是指正序和倒序读都相同的数字,例如121、1331等。这个问题看似简单,却蕴含着算法设计中关于效率优化和边界条件处理的重要思想。
在实际编程中,我们经常会遇到需要验证输入数据合法性的场景。比如在开发一个会员系统时,可能需要检查用户输入的身份证号、银行卡号等数字是否符合特定规则。回文数判断就是这类基础验证的典型代表。
判断一个整数是否为回文数,核心在于比较数字的正序和逆序表示。根据这个基本思路,我们可以衍生出三种主要解法:
每种方法都有其适用场景和优缺点,我们需要深入理解它们的实现细节和性能特征。
无论采用哪种方法,都需要特别注意以下边界情况:
字符串法是最直观的解决方案,其核心思想是将整数转换为字符串后,使用双指针技术从两端向中间比较字符是否相同。
c复制#include <stdio.h>
#include <stdbool.h>
#include <string.h>
bool isPalindrome(int x) {
if (x < 0) return false;
char str[20];
sprintf(str, "%d", x);
int left = 0;
int right = strlen(str) - 1;
while (left < right) {
if (str[left] != str[right]) {
return false;
}
left++;
right--;
}
return true;
}
提示:虽然这种方法代码简单易懂,但在C语言中需要处理字符串转换,且空间效率不高,通常不是最优解。
这种方法通过数学运算将数字完全反转,然后比较反转前后的数值是否相等。
c复制#include <stdbool.h>
bool isPalindrome(int x) {
if (x < 0) return false;
long reverse = 0;
int temp = x;
while (temp != 0) {
reverse = reverse * 10 + temp % 10;
temp /= 10;
}
return reverse == x;
}
注意事项:虽然这种方法空间效率高,但对于极大整数(如2147483647),反转后可能导致溢出,即使使用long类型也存在风险。
这是LeetCode官方推荐的最优解法,核心思想是只反转数字的后半部分,然后与前半部分比较。这种方法巧妙地避免了完全反转可能导致的溢出问题。
c复制#include <stdbool.h>
bool isPalindrome(int x) {
// 特殊情况处理
if (x < 0 || (x % 10 == 0 && x != 0)) {
return false;
}
int reversed = 0;
// 反转过程
while (x > reversed) {
reversed = reversed * 10 + x % 10;
x /= 10;
}
// 比较判断
return x == reversed || x == reversed / 10;
}
预处理排除:
反转过程:
最终比较:
以x=12321为例:
| 方法 | 时间复杂度 | 空间复杂度 | 优点 | 缺点 |
|---|---|---|---|---|
| 字符串法 | O(n) | O(n) | 实现简单 | 需要额外空间 |
| 完全反转 | O(log n) | O(1) | 空间效率高 | 可能溢出 |
| 半反转法 | O(log n) | O(1) | 最优效率 | 逻辑稍复杂 |
在实际应用中,推荐优先掌握半反转法,因为:
虽然本文以C语言为例,但这些算法思想可以轻松移植到其他语言:
掌握回文数判断后,可以尝试解决以下类似问题:
在实际编码时,我发现半反转法虽然效率最高,但对于初学者来说理解起来可能有些困难。建议可以先实现字符串法,确保理解回文数的基本概念后,再逐步过渡到更高效的解法。另外,在面试中即使被要求用特定语言实现,也要主动讨论不同解法的优劣,这能展现你的算法思维深度。