回文数
每天一道算法题,今天是第一天,目标是写到第一千天,希望我可以做到
编号:0001
本文使用的编程语言
c++
,算法题来源leetcode
题目描述
判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。(待判断的整数在int
范围内)
示例输入输出
-
示例1:
输入:121
输出:true
-
示例2:
输入:-121
输出:false
解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
-
示例3:
输入:10
输出:false
解释:从右向左读, 为 01 。因此它不是一个回文数。
题解
转换为字符串
把int
类型的数字转换成char
类型的数组,然后第一位和最后一位对比,第二位和倒数第二位对比,依次类推。
因为负数一定不是回文数,因此先对负数进行判断排除。
class Solution {
public:
bool isPalindrome(int x) {
if(x < 0 || (x % 10 == 0 && x != 0)) //负数和尾数为0的非零数不是回文数
return false;
char temp[10]; //定义一个数组,存放int
int i = 0;
while (x != 0) //遍历数字x的每一位,把它放在数组中
{
temp[i++] = x % 10 + '0';
x = x / 10;
}
int l = i;
for (i = 0; i < l / 2; i++) //数组temp中前后进行比较,若中间任何一次比较不等,返回false
if (temp[i] != temp[l - 1 - i])
return false;
return true;
}
};
不用转换为字符串
完整比较
如果是12321这个数字,可以通过x/10000得到最高位,x%10得到最低位,然后进行比较;在通过(x%10000)/10得到232这个新的要比较的数,进行上述操作;一直到x小于10为止。
同样的负数一定错误,因此先对负数进行判断。
class Solution {
public:
bool isPalindrome(int x){
if(x < 0 || (x % 10 == 0 && x != 0)) //负数和尾数为0的非零数不是回文数
return false;
int div = 1;
while(x / div >= 10){div *=10;} //找到要求的最高位被除数div
while(x > 0)
{
if(x / div != x % 10) //比较当前最低位和最高位是否相同
return false;
x = (x % div) / 10; //生成新的比较数
div /= 100; //注意整个数字少了2位,因此div/100
}
return true;
}
};
完整比较除了像上面一样,本质上还是字符的角度,进行从前到后的一一对应,还可以生成一个逆转的数字,也就是说新数字的最高位是原数字的最低位,如果新生成的数字和原数字相同,那么显然原数字就为回文数。
这里面需要注意逆转数可能超过int
的表示范围,因此要注意判断溢出数,又因为溢出的时候显然不是回文数,直接返回false
就可以
class Solution {
public:
bool isPalindrome(int x){
if(x < 0 || (x % 10 == 0 && x != 0)) //负数和尾数为0的非零数不是回文数
return false;
int reverse = 0, temp = x; //reverse存储逆转后的数字,temp表示原来的数
while(temp > 0)
{
if (reverse > INT_MAX / 10) //判断是否会溢出,如果reverse溢出,那么显然原数字不可能是回文数
return false;
reverse = reverse * 10 + temp % 10; //把temp的最低位变成reverse的较高位
temp /= 10;
}
return (reverse == x); //直接判断reverse和原数字是否一样即可
}
};
不完整比较
不完整算法的基本思路和完整比较的第二种比较类似,但是为了回避掉逆转数可能溢出的问题,我们可以只将原数字的一半进行逆转。例如说对1221进行判断,我们只要将其一半进行逆转,也就是21逆转为12,与原数字前一半相同,是回文数。
这里面的关键是如何判断我们已经逆转了一半,可以简单通过reverse >= x作为判断标准
class Solution {
public:
bool isPalindrome(int x){
if(x < 0 || (x % 10 == 0 && x != 0)) //负数和尾数为0的非零数不是回文数
return false;
int reverse = 0;
while(x > reverse) //判断仅逆转一半
{
reverse = reverse * 10 + x % 10;
x /= 10;
}
//当数字长度为奇数时,我们可以通过 reverse/10 去除处于中位的数字。
return (reverse == x || reverse / 10 == x);
}
};
参考题解:
[1] https://leetcode-cn.com/problems/palindrome-number/solution/hui-wen-shu-by-leetcode/