出处
描述
判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
示例
输入: 121
输出: true
输入: -121
输出: false
解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
输入: 10
输出: false
解释: 从右向左读, 为 01 。因此它不是一个回文数。
分析
首先理解回文数的定义。说白了就是倒过来跟原数一样就是回文数。
方法1:借助字符串实现
那么自然我们就可以想象到把这个数直接倒过来判断是否和原数一样就可以了。 这里就想到了最容易想到的方法,把数转换成字符串,然后字符串反转就可以了。
方法2:不使用字符串实现
本题中有一个挑战,是否可以不借助字符串完成? 如果不使用字符串就有一点难度了,怎么才能反转一个数字呢? 无论是反转数字还是字符串,我们都需要把最后边的一位一步一步的移动到前面,或者把最前面的一位一步一步的移动到后面。一个数字我们怎么才能获取到他最高位或者最低位呢,最高位一次获取很难,但是最低位的话我们可以很容易想到,借助取余就可以实现,原数除以10,就将原来的数字分成了两部分
例子: 数字 1234
1234 % 10 = 4
1234 / 10 = 123
那么我们再把123重复这个步骤把3取出来,然后再依次取2,取1,再拼接到新组成的数字上不就完成了反转了嘛,怎么拼接这个很容易想到,4 * 10 + 3 = (43) ,就将3拼接到了4的后面,依次重复讲取出来的数字拼接,最后就得到了反转之后的数了。
但是这里注意越界的问题。还有特殊情况 如 被10整除的数,0,负数等。
其实通过栈的先进后出的特性我们也可以实现。
方法3:只反转后半段
这样问题就解决啦!但是发现没有,回文数的第一位与最后一位相同,第二位与倒数第二位相同。。。 也就是说它的前半段和后半段调转过来一致
- 回文数如果是偶数位,则前半段和后半段调转过来一致
123321 前半段123 与 321调转过来一致
- 回文数如果是奇数位,则除了中间位,前半段和后半段调转过来一致
1234321 前半段123 与321调转过来一致
也就是说如果一个数是回文数的话,我们只要转换一半位就可以知道 是不是回文数了,完全不需要将数字全部反转过来。
方法与上边相同,但是这个需要重点看一下临界条件,还有特殊情况
- 当回文数为偶数位时,保留的数字与反转的数字位数相同,且相等
- 当回文数为奇数位时,当保留的数字小于反转的数字时则说明当前旋转的数字是最中间位
综上所述,当保留的数字大于反转的数字时,我们进行转换,如果保留的文字不大于反转的数字时(等于的情况为偶数情况和特殊情况0,小于的情况为奇数情况),说明我们已经将后半段的数字全部反转,随即将反转的数字与原数字进行比较,此处还是分成两种情况
- 当数字为偶数位时,反转的数字应该与源数字相同
- 当数字为奇数位时,由于最中间位的数字在反转的数字中,所以此时 反转的数字/10 与 源数字 相同
过程追踪
以1234321为例
设 原数为current,初始值为1234321
设 反转数字为reverse,初始值为0
设每一次反转的时候,预反转的数字为pop,由 current%10 计算得到
循环条件为:current > reverse
- 第一步:此时current: 1234321 reverse: 0 循环条件达成,进入循环
- 计算pop为1,current使用表达式current/10 移除要反转的数字,结果为123432
- 将pop拼接到reverse上,使用表达式reverse = reverse * 10 + pop,计算得到reverse为1
- 循环结束
- 第二步:此时current: 123432 reverse: 1 循环条件达成,进入循环
- 计算pop为2,current使用表达式current/10 移除要反转的数字,结果为12343
- 将pop拼接到reverse上,使用表达式reverse = reverse * 10 + pop,计算得到reverse为12
- 循环结束
- 第三步:此时current: 12343 reverse: 12 循环条件达成,进入循环
- 计算pop为1,current使用表达式current/10 移除要反转的数字,结果为1234
- 将pop拼接到reverse上,使用表达式reverse = reverse * 10 + pop,计算得到reverse为123
- 循环结束
- 第四步:此时current: 1234 reverse: 123 循环条件达成,进入循环
- 计算pop为4,current使用表达式current/10 移除要反转的数字,结果为123
- 将pop拼接到reverse上,使用表达式reverse = reverse * 10 + pop,计算得到reverse为1234
- 循环结束
- 第五步:此时current: 123 reverse: 1234 未打成循环条件,跳出循环
- 第六步:比较是否current是否与reverse相同(位数为偶数情况)或者current是否与reverse/10相同(位数为奇数情况)
题解
class Solution {
public boolean isPalindrome(int x) {
// 解法2:转换一半数字即可
if (x < 0 || x % 10 == 0 && x > 0) {
return false;
}
int current = x;
int reverse = 0;
while (current > reverse) {
int pop = current % 10;
current = current / 10;
reverse = reverse * 10 + pop;
}
return reverse == current || reverse / 10 == current;
// 解法1:转换数字与原数对比
if (x < 0) {
return false;
}
int reverse = 0;
int current = x;
while (x != 0) {
int pop = x % 10;
if (reverse > Integer.MAX_VALUE || reverse == Integer.MAX_VALUE / 10 && pop > Integer.MAX_VALUE % 10) {
return false;
}
x /= 10;
reverse = reverse * 10 + pop;
}
return reverse == current;
}
}