这是一道很有意思的题,首先来看一下题目:
一、题目与分析
判断一个数是否是回文序列,不使用额外的空间;
首先一个数怎么是回文呢?很简单,比如:123321,111111,12321等等,这样的数就叫回文数;
那么判断回文最直接的思路就是先把这个序列反转,然后看看反转之后的结果是不是和原序列相同,如果相同那就是回文,如果不同就不是。而且我们在第7题的时候已经解决了反转数字的问题,那么这道题也就迎刃而解了,只不过有两点需要注意:
- 负数一定不是回文;
- 如果在反转的过程中发生了越界,那原数字也一定不是回文;
对于int来说,所能表示的最大数字就是2147483647,那么最大的回文就是2147447421,这个数字在反转的过程中不会越界,对于比这个数还大的回文数,在一开始的时候就不可能用int表示,所以一旦在反转的过程中发生越界,我们直接返回false;
二、代码
class Solution {
public:
bool isPalindrome(int x)
{
if(x < 0) return false;
//记录原数字
int orig = x;
//求原数字的反转数
int rev = 0;
while(x)
{
int temp = rev * 10 + x % 10;
//如果发生了越界,那么原数字一定不是回文数
if(temp / 10 != rev) return false;
rev = temp;
x /= 10;
}
//判断是否是回文数
if(rev == orig) return true;
else return false;
}
};
三、另一种思路
如果你做过回文链表的问题,那么对于这道题来说你一定可以想到一个更好的解法,我们不需要反转整个数字,我们只需要反转一半,如果反转后的这一半与原数字剩下的那一半相同,那原数字肯定就是回文,使用这种方法可以无需担心越界的问题,我们只需要考虑如何判断数字已经反转了一半;
我们知道,在反转的过程中,原数字每次迭代都减少一位,而反转的结果会增加一位,那么当反转结果的位数等于原数字的位数时,反转就完成了一半,那么在这之前,原数字一定一直大于反转结果,我们利用这个思路就可以判断在何时停止迭代!但是需要注意如何处理有奇数个位的情况,比如12321这种数字,迭代将在原数字为12,反转数为123的时候停止,那么我们只需要将反转数除以10再与原数字判断即可!
代码:
class Solution {
public:
bool isPalindrome(int x)
{
//如果x非零并且为10的倍数,则返回false
if(x != 0 && x % 10 == 0) return false;
//将x从中间分开,从低位开始逆转,判断两部分是否相等
//sum用来存储低位逆转后的结果
int rev = 0;
while(x > rev)
{
rev = rev * 10 + x % 10;
x /= 10;
}
return rev == x || rev / 10 == x;
}
};
如果你按照上面的思路写好了代码,那么提交的时候你会发现这样一个问题:所有大于0的10的倍数不能通过测试,原因顺着代码一看便知,我们只要在开头加上一行判断语句即可,反正这样的数肯定不是回文数!