2021.5.6
题目:
给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。
如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。
假设环境不允许存储 64 位整数(有符号或无符号)。
示例 2:
输入:x = -123
输出:-321
解题思路:
首先我们想一下,怎么去反转整数呢?
用栈?
或者把整数变成字符串,再去反转这个字符串?
这两种方式是可以,但并不好。实际上我们只要能拿到这个整数的 末尾数字 就可以了。
以12345为例,先拿到5,再拿到4,之后是3,2,1,我们按这样的顺序就可以反向拼接处一个数字了,也就能达到 反转 的效果。
(1)怎么拿末尾数字呢?好办,用取模运算就可以了,要在没有辅助栈或数组的帮助下「弹出」和「推入」数字,我们可以使用如下数学方法:
// 弹出 x 的末尾数字 digit
digit = x % 10
x /= 10
// 将数字 digit 推入 rev 末尾
rev = rev * 10 + digit
(2)接下里我们思考一下,循环的终止条件是什么?
x>0嘛,那么你就只考虑到了正数的情况了。循环的判断条件应该是while(x!=0)
,无论正数还是负数,按照上面不断的/10
这样的操作,最后都会变成0
,所以判断终止条件就是!=0。
(3)最后也是最关键的,就是考虑溢出问题!!
请注意题目的关键句假设环境不允许存储 64 位整数(有符号或无符号),也就是说我们不能用long
存储最终结果,而且有些数字可能是合法范围内的数字,但是反转过来就超过范围了。
因为我们是通过rev = rev * 10 + pot来不断累加获取到最后反转的数字,所以对于大于 intMax 的讨论,此时 x 一定是正数,pop 也是正数。
- 如果 rev > intMax / 10 ,那么没的说,此时肯定溢出了。(int最大值是2147483647,如果rev>214748364,那么rev=rev*10+pot肯定大于2147483647)
- 如果 rev == intMax / 10 = 2147483647 / 10 = 214748364 ,此时 rev * 10 就是 2147483640 如果 pop 大于 7 ,那么就一定溢出了。但是!如果假设 pop 等于 8,那么意味着原数 x 是 8463847412 了,输入的是 int ,而此时是溢出的状态,所以不可能输入,所以意味着 pop 不可能大于 7 ,也就意味着 rev == intMax / 10 时不会造成溢出。
- 如果 rev < intMax / 10 ,意味着 rev 最大是 214748363 , rev * 10 就是 2147483630 , 此时再加上 pop ,一定不会溢出。
- 综上,如果res>intMax/10,则溢出!
- 对于小于 intMin 的讨论同理。
代码:
class Solution {
public int reverse(int x) {
int res=0;
while(x!=0){ //注意是x!=0,才包含正负两种情况
int tmp=x%10;
if(res>Integer.MAX_VALUE/10 || res<Integer.MIN_VALUE/10)
return 0;
res=res*10+tmp;
x=x/10;
}
return res;
}
}
类似题目:
力扣第八题:字符串反转 https://leetcode-cn.com/problems/string-to-integer-atoi/
力扣第九题:回文数 https://leetcode-cn.com/problems/palindrome-number/