【题目描述】
给你一个整数 x
,如果 x
是一个回文整数,返回 true
;否则,返回 false
。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
例如,121
是回文,而 123
不是。
【测试用例】
示例1:
输入:x=121
输出:true
示例2:
输入:x=-121
输出:false
解释:从左向右读,为-121。从右向左读,为121-。因此它不是一个回文数。
示例3:
输入:x=10
输出:false
解释:从右向左读,为01。因此它不是一个回文数。
【思路分析】
因为题目说的是整数,所以这里没有考虑回文字符串的情况。
首先,负数一定不是回文数;末位为0的数也一定不是回文数,因为一个整数的最高位不为0。
按照正常数学思路来判断一个整数是不是回文数,就是顺着读和倒着读是否一样,也就是从最高位读到个位和从个位读到最高位是否一样。按照这个想法,最高位到个位很简单,因为输入的数据本来就是这么存的,所以问题的本质就是如何把这个数按照从个位到最高位的顺序读出来(不是简单的一个一个的读,还要按照读的顺序放在对应的数位上,第一个读的放在最高位,第二个读的放在次高位...)
在程序中要实现这样的操作也很简单,就是通过不断的除10取余来得到最低位,然后再将原数/10得到去掉最低位的数。
输入的整数为x,设置一个变量sum来存反着读的数,初始化为0;再设置一个变量tmp用于不断循环,初始化为输入的整数x。每次通过sum=sum*10+tmp%10来得到反读的数,通过tmp=tmp/10来得到去掉最低位的数,当tmp=0(可以理解为反读已经读到了原数的最高位)时循环结束。
注意:
我前两次在LeetCode中测试用例都通过了,但是两次提交都没有AC,都出现如下错误:
报错信息很明了:整形溢出了。int类型的最大值为2147483647,这里的用例是1234567899,翻转之后9987654321大于了2147483647,所以溢出了。
解决方法:将sum的类型改为无符号类型unsigned。(改为double/long long类型应该也是没问题的)
【参考代码】
C语言实现
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
//easy-9-回文数
bool isPalindrome(int x);
int main(){
int x;
scanf("%d",&x);
bool res = isPalindrome(x);
if(res==false){
printf("false\n");
}else{
printf("true\n");
}
}
bool isPalindrome(int x){
if(x<0 || x>=(pow(2,31)-1) || (x%10==0 && x!=0)){//负数一定不是回文数;末位为0时一定不是回文数,因为最高位一定不是0
return false;
}else{
int tmp=x;
unsigned sum=0;
while(tmp!=0){
sum = sum * 10 + tmp % 10;
tmp = tmp / 10;
}
if(sum==x){
return true;
}else{
return false;
}
}
}
C++实现
#include <iostream>
#include <cmath>
using namespace std;
//easy-9-回文数
class Solution{
public:
bool isPalindrome(int x) {
if(x<0 || x>=(pow(2,31)-1) || (x%10==0 && x!=0)){//负数一定不是回文数;末位为0时一定不是回文数,因为最高位一定不是0
return false;
}else{
int tmp=x;
unsigned sum=0;
while(tmp!=0){
sum = sum * 10 + tmp % 10;
tmp = tmp / 10;
}
if(sum==x){
return true;
}else{
return false;
}
}
}
};
int main(){
Solution sol;
int x;
cin>>x;
bool res = sol.isPalindrome(x);
if(res){
cout<<"true";
}else{
cout<<"false";
}
}
【改进】
在上面的代码中,循环条件是tmp!=0,但是对于回文数来说,它是严格对称的,也就是说实际我们只需要反转一半数字就可以了,那么如何知道已经反转了一半数字呢?由于在循环中我们不断地将原始数字/10,然后给反转后的数字*10,所以当原始数字小于或等于反转后的数字时即表示已经反转了一半数字。这样,不但提高了程序的运行效率,还可以避免int溢出的情况。
对于输入整型数为偶数时,例如,输入1221,我们只需要反转一半,也就是后两位21反转为12,如果反转一半后的数与剩下的前半部分相同,循环结束后,sum=12,tmp=12,此时用tmp==sum可以判断此数是回文数。
对于输入整型数为奇数时,例如,输入121,循环结束后,sum=12,tmp=1,此时用tmp==sum/10可以判断此数是回文数。因为对于奇数位数来说,正中间位置上的数字不影响反转(它总是等于它自己,所以可以直接/10去除它)。
【改进后参考代码】
#include <iostream>
#include <cmath>
using namespace std;
//easy-9-回文数
class Solution{
public:
bool isPalindrome(int x) {
if(x<0 || x>=(pow(2,31)-1) || (x%10==0 && x!=0)){//负数一定不是回文数;末位为0时一定不是回文数,因为最高位一定不是0
return false;
}else{
int tmp=x;
unsigned sum=0;
while(tmp>1sum){
sum = sum * 10 + tmp % 10;
tmp = tmp / 10;
}
if(tmp==sum || tmp==(sum/10)){
return true;
}else{
return false;
}
}
}
};
int main(){
Solution sol;
int x;
cin>>x;
bool res = sol.isPalindrome(x);
if(res){
cout<<"true";
}else{
cout<<"false";
}
}
改进后的代码性能提高明显: