回文数原题地址
方法一:反转一半数字
考虑特殊情况:
- 负数不是回文数,如 -123 ,反过来为 321- 。
- 个位数为零的非零数不是回文数,比如 120 ,反过来为 021 。
对于一般情况,我们只需要取出后半段反转再跟前半段比较,若相等或差一位,则原数是回文数。如:
- 12321 ,后半段 321 反转为 123 ,前半段 12 , 123 和 12 差一位,是回文数。
- 1221 ,后半段 21 反转为 12 ,前半段 12 , 12 和 12 相等,是回文数。
- 12324 ,后半段 324 反转为 423 ,前半段 12 , 423 和 12 既不相等,也不是差一位,不是回文数。
- 1223,后半段 23 反转为 32 ,前半段 12 , 32 和 12 既不相等,也不是差一位,不是回文数。
为什么不是直接反转整体呢?因为反转后的数据有可能超出INT_MAX,导致溢出。
注意到整数操作的3个技巧:
- xmod10 可以取出 x 的最低位。如 x=123 , xmod10=3 。
- x=x*10+y ,0≤y≤9 ,可以在 x 后面续上 y 。如 x=123 , y=4 ,那么经过这个操作后 x=1234 。
- x/=10 可以去掉 x 的最低位。如 x=123 , x/=10 , x=12 。
如何反转呢?取 r=0 ,每次用技巧 1 取出 x 的最低位,再用技巧 2 续到 r 上,最后用技巧 3 去掉 x 的最低位。如:
- x=12321 , r=0→x=1232 , r=1→x=123 , r=12→x=12 , r=123 。
- x=1221 , r=0→x=122 , r=1→x=12 , r=12 。
什么时候才处理完一半的位数呢?显然, r 的位数越来越大, x 的位数越来越小,当 r 的位数 ≥x 的位数时,即 r≥x 时就处理完了。偶数位的回文数处理到最后满足 x==r (参考一般情况的案例 1 ),奇数位的回文数处理到最后满足 x==r/10 (参考一般情况的案例 2 )。如果不满足 x==r 或 x==r/10 ,则不是回文数。
// 方法一:反转一半数字
class Solution
{
public:bool isPalindrome(int x){// 负数和个位数为零的非零数if (x < 0 || (x % 10 == 0 && x != 0)){return false;}// 反转 x 右半边的数字int rev = 0;// 当 rev 的位数超过 x (或相等)时// 说明反转了一半的数字while (rev < x){// 把 x 的最低位续到 rev 上rev = rev * 10 + x % 10;// 去掉 x 的最低位x /= 10;}// 此时 rev>=x// 若 x 原本是回文数,则此时 x 和 rev 相等或者差一位return x == rev || x == rev / 10;}
};
方法二:字符串
我们也可以先把整数转换为字符串,再判断字符串是否为回文串。
整数转换为字符串可以使用整数处理技巧 2 和 3 ,每次取出最低位插入到字符串中,这样转换出来的字符串和原来的整数是反过来的,如 123 转换为字符串后就变成了 "321" ,但是是否回文的性质不变。也可以直接调用库里的方法,如 C++ 中的 to_string 。
判断回文串的思路是:取2个指针指向最左边和最右边的字符,从2边向中间移动,判断沿途的字符是否相同,如果都相同就是回文串。或者直接判断反转后的字符串是否和原字符串相同。
// 方法二:字符串
class Solution
{
public:bool isPalindrome(int x){string s1, s2;s1 = s2 = to_string(x);reverse(s1.begin(), s1.end());return s1 == s2;}
};