官方题解已经说的很清楚了,
这样只记录自己实现过程中遇到的问题,
但最终并未解决、、、
还是请大家以官方题解为准:https://leetcode-cn.com/problems/reverse-integer/solution/
老师在讲《安全程序设计》这门课时,
开篇就是整数安全,
当时不以为然,
现在吃了大亏才明白。
附上本人写得代码:
class Solution { public: int reverse(int n) { int ans = 0,pop = 0; //ans是最终输出,pop是每次取出的最末尾的数字 bool flag = true; //用来区分是正数还是负数,此处有重大问题,接下来会讲到。
if(n < 0) { //如果是负数,变成正数来处理。想法很简单,但其实有很大的问题 flag = false; n = 0 - n; } while(n != 0) { pop = n % 10; n /= 10; if(ans > INT_MAX/10) return 0; //越界可能情况1 if(ans == INT_MAX/10) { //越界可能情况2 if(pop > 9) return 0; if(flag && pop == 8) return 0; } ans = 10 * ans + pop; } if(!flag) ans = 0 - ans; return ans; } };
关于第17、18两行:
注意到INT32的取值范围是从:-2147483648~2147483647,
注意最后最后一位:
如果是负数,不能超过8;
如果是正数,则不能超过7。
也就是说,不论正数还是负数,最后一位都不能是9,
如果是正数,也不是8。
关于我一开始分正负数讨论的想法,问题出在了:
对于负数,我统一取了绝对值,
但是-2147483648取绝对值变成了2147483648
INT32最大正数只能是2147483647
于是溢出,产生了回绕现象——变成了-2147483648
我们将每次运算的结果输出出来,就可以看得很清晰
结果就一目了然了,
虽然我们取了绝对值,
但是n变成2147483648之后溢出成了-2147483648,
所以pop和n都变成了负数。
恕本人水平有限,
想到的解决方案是将pop和n绝对值化,
即在while(n != 0)内:
将pop = n%10变成pop = abs(n%10)
如果以后能想到更好的办法,
会更新此文,
最后是20ms过了本题
最终代码:
class Solution { public: int reverse(int n) { int ans = 0, pop = 0; bool flag = true; if (n < 0) { flag = false; n = 0-n; } while (n != 0) { pop = abs(n % 10); n /= abs(10); if (ans > INT_MAX / 10) return 0; if (ans == INT_MAX / 10) { if (pop == 9) return 0; if (flag && pop == 8) return 0; } ans = 10 * ans + pop; } if (!flag) ans = 0 - ans; return ans; } };