题目https://leetcode-cn.com/problems/palindrome-number/
判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
示例 1:
输入: 121
输出: true
示例 2:
输入: -121
输出: false
解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
示例 3:
输入: 10
输出: false
解释: 从右向左读, 为 01 。因此它不是一个回文数。
方法一:暴力法
比较多的人一来就想着使用暴力法解这个题,这也是可行的。
使用一个变量储存x(判断是否是回文数的数)的逆序数,在最后的时候判断这个临时变量跟x是否相等。
但是使用这个方法再过样本测试的时候会出错,主要原因在于将一个数反转后,很可能超出这个整数的范围,所以我们需要判断是否在整数范围之内。这个跟我之前写的整数反转的原理一样,有兴趣的可以去看一下传送门
我先贴代码进行讲解吧。
class Solution {
public:
bool isPalindrome(int x)
{
if (x < 0)
return false;
int temp = 0, rem = 0, x2 = x;
while (x)
{
rem = x % 10;
if (temp > INT_MAX / 10 || (temp == INT_MAX && rem > 7))
return false;
temp = temp * 10 + rem;
x /= 10;
cout << temp << endl;
}
return x2 == temp;
}
};
// 很容易看出,负数一定不属于回文数,所以如果x小于0则直接返回false。
// temp 表示临时变量,rem是取x后面的尾数
// 问题在于,处理一个反转后超出范围的数
// 情况一:如果temp>INT_MAX/10,那么这个数反转后一定是超出范围的
// 情况二: 如果temp == INT_MAX/10,并且rem>7也是超出范围的
可能会有初学的小伙伴会问为什么是 rem>7,因为INT_MAX = 2147483647,我们的rem是加入到temp的末尾,如果temp==INT_MAX/10,那么加上rem后也是会超出范围。
方法二:字符串转换
还有一种比较好理解的方法就是将这个整数转换成字符串,然后创建两个指针,分别做为头指针和尾指针,如果指针指向的元素相等,则头指针往前移动,尾指针往后移动。不相等直接返回。直到头指针大于尾指针的位置就停止。这个双指针的题目我也写过一个传送门
class Solution {
public:
bool isPalindrome(int x)
{
if(x<0)
return false;
string temp = to_string(x);
int pre = 0, back = temp.size() - 1;
while (pre <= back)
{
if (temp[pre] != temp[back])
{
return false;
}
pre++;
back--;
}
return true;
}
};
方法三:将整数反转一半
有了第一个暴力破解的基础后,在想能不能说把一个整数劈开成两半,这样就不用去考虑整数范围了。
问题就在于,我们应该怎么样判断出是否已经取到了中间的数。
如果我们在取数的过程中,x的值小于或者等于reverse的值,则说明已经取到了中间值。
如果给的是一个奇数,那我们只需要把reverse末尾的数给去除掉即可,因为他总是与自身相等
class Solution {
public:
bool isPalindrome(int x)
{
if (x < 0 || (x%10 == 0 && x!=0))
return false;
int reverse = 0, rem = 0;
while (x > reverse)
{
rem = x % 10;
reverse = reverse * 10 + rem;
x /= 10;
}
return x == reverse || x == reverse / 10;
}
};
// 关于为什么(x%10 == 0 && x!=0)返回false
// 这是因为,如果末尾数字是0,那么x不是0则不是回文数。这里是不考虑0开头的整数的。像00100这样的数是不在考虑范围的。
// 只能传入非0开头的数
这篇文章就到这里。我是小白。
跟我一起变强可以关注我的公众号。每天分享leetcode的算法题解,和一些科技见闻。