数学与数字3:整数反转-溢出的统一处理法则
Posted 纵横千里,捭阖四方
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数学与数字3:整数反转-溢出的统一处理法则相关的知识,希望对你有一定的参考价值。
这是一道经典的问题,听名字也不复杂是不?但是却是一位小伙伴面试美团的原题:
所以我们千万不要只觉得回溯、dp才叫算法,先看一下题目要求吧:
给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。
如果反转后整数超过 32 位的有符号整数的范围 [−2^31, 2^31 − 1] ,就返回 0。
假设环境不允许存储 64 位整数(有符号或无符号)。
这个题的关键在哪里呢?两点,一个是进行数字反转,另一个是如何判断溢出。溢出的判断在很多与整数有关的题目中都会出现,例如 字符串转整数的问题等等,处理策略基本是一致的。所以我们必须要学会。
1.如何反转
首先想一下,怎么去反转一个整数?用栈?或者把整数变成字符串,再去反转这个字符串?这两种方式是可以,但并不好。实我们只要能拿到这个整数的 末尾数字 就可以了。
以12345为例,先拿到5,再拿到4,之后是3,2,1,我们按这样的顺序就可以反向拼接处一个数字了,也就能达到 反转 的效果。而末尾数字呢?好办,用取模运算就可以了。例如:
1、将12345 % 10 得到5,之后将12345 / 10
2、将1234 % 10 得到4,再将1234 / 10
3、将123 % 10 得到3,再将123 / 10
4、将12 % 10 得到2,再将12 / 10
5、将1 % 10 得到1,再将1 / 10
这么看起来,一个循环就搞定了,循环的判断条件是x>0,但这样不对,因为忽略了负数的问题。
循环的判断条件应该是while(x!=0),无论正数还是负数,按照上面不断的/10这样的操作,最后都会变成0,所以判断终止条件就是!=0
有了取模和除法操作,就可以轻松解决第一个问题,如何反转。
2.如何解决溢出问题
如何解决溢出问题描述比较复杂,网上的解释很多,但是很多写得晦涩难懂,找到这个解释,还是比较好的。我们贴过来看一下。
根据题目的要求,不能超过32位,也就是说我们不能用long存储最终结果,而且有些数字可能是合法范围内的数字,但是反转过来就超过范围了。
假设有1147483649这个数字,它是小于最大的32位整数2147483647的,但是将这个数字反转过来后就变成了9463847411,这就比最大的32位整数还要大了,这样的数字是没法存到int里面的,所以肯定要返回0(溢出了)。甚至,我们还需要提前判断
上图中,绿色的是最大32位整数
第二排数字中,橘子的是5,它是大于上面同位置的4,这就意味着5后跟任何数字,都会比最大32为整数都大。
所以,我们到【最大数的1/10】时,就要开始判断了
如果某个数字大于 214748364那后面就不用再判断了,肯定溢出了。
如果某个数字等于 214748364呢,这对应到上图中第三、第四、第五排的数字,需要要跟最大数的末尾数字比较,如果这个数字比7还大,说明溢出了。
这个对于负数也是一样的。
上图中绿色部分是最小的32位整数,同样是在【最小数的 1/10】时开始判断
如果某个数字小于 -214748364说明溢出了
如果某个数字等于 -214748364,还需要跟最小数的末尾比较,即看它是否小于8。
实现代码:
class Solution
public int reverse(int x)
int res = 0;
while(x!=0)
//每次取末尾数字
int tmp = x%10;
//判断是否 大于 最大32位整数
if (res>214748364 || (res==214748364 && tmp>7))
return 0;
//判断是否 小于 最小32位整数
if (res<-214748364 || (res==-214748364 && tmp<-8))
return 0;
res = res*10 + tmp;
x /= 10;
return res;
以上是关于数学与数字3:整数反转-溢出的统一处理法则的主要内容,如果未能解决你的问题,请参考以下文章