题目描述
判断一个整数是否是回文数。回文数是指 正序(从左向右)和倒序(从右向左)读都是一样的整数。
我的题解
不管什么方法,可以先把几种情况去掉:
- 负数
- 以0结尾的正数
解法1
先使用最笨的方法:转化为字符串,然后调用相关的reverse函数,最后比较
//Java
public boolean isPalindrome(int x) {
if (x>=0){
String tmp = Integer.toString(x);
String revStr = new StringBuilder(tmp).reverse().toString();
if (revStr.equals(tmp))return true;
}
return false;
}
解法2
可以不使用内置的反转函数,自行判断。
public boolean isPalindrome(int x) {
if (x<0||x%10==0) return false;
String str = Integer.toString(x);
for (int i=0,j=str.length()-1;i<j;i++,j--){
if (str.charAt(i)!=str.charAt(j))return false;
}
return true;
}
这个解法也不是很好,因为还是在基于字符串的操作,这是既耗时,也耗空间,如何才能彻底摆脱字符串?
其他解法
把整个数字反转,然后和原数字比较是可行的,但是出现两个问题:
- 可能造成溢出。必须使用更宽的整数类型来存放反转的结果。
- 全部反转比较麻烦
于是考虑:只反转低位一半的数字,然后和另一半处理。
需要解决几个问题:
-
怎么实现反转?
每次取出最低位,反转数乘以10以后加上去(原来的低位变为了高位:通过每次乘以10实现)
考虑:123
int res = 0;
先取出最低位3,res = res * 10+3 = 3
再取出2,res = 3 * 10+2 = 32
最后取出1, res = 32 * 10+1 = 321
于是实现了反转 -
‘一半’怎么判定,奇数位怎么办?
对于一个数,到底什么时候应该停止反转。
可以通过比较大小判断。
如果反转后的数 >= 剩余的数,则停止反转。
对于偶数: 反转过程中,若是回文,左右会出现相同而停止,如123321,反转一半后一定相同,所以才会有停止条件>=
若非回文,停止时不一定相同,如999111,反转为99,1111才会停止,而111999则会是111,999,但是这并不影响判断。
对于奇数:一定是反转的多一位才会停止,,中间这位不会影响回文判断,最后是反转数的最低位,去掉即可
根据上面的分析,有代码(java):
public boolean isPalindrome(int x) {
if (x<0 || (x!=0&&x%10==0)) return false; //直接去掉不是回文的:负数,0结尾的正数
int rev = 0;
while(x>rev){
rev = rev + x%10;
x/=10;
}
return x==rev || x==rev/10; //偶数、奇数情况
}
彻底摆脱了字符串
性能比基于字符串的实现好:
- 时间复杂度:O(log10(N)), 每次除10,时间复杂度^10 = N
- 空间复杂度:O(1)