LeetCode - 7. 整数反转

tech2023-02-14  121

给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。

示例 1:

输入: 123 输出: 321  示例 2:

输入: -123 输出: -321 示例 3:

输入: 120 输出: 21 注意:

假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231,  231 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。

上面是题目。官方给出的答案确实是挺棒的,逻辑完美,代码简洁。先把官方的代码贴上来吧:

class Solution { public int reverse(int x) { int rev = 0; while (x != 0) { int pop = x % 10; x /= 10; if (rev > Integer.MAX_VALUE/10 || (rev == Integer.MAX_VALUE / 10 && pop > 7)) return 0; if (rev < Integer.MIN_VALUE/10 || (rev == Integer.MIN_VALUE / 10 && pop < -8)) return 0; rev = rev * 10 + pop; } return rev; } }

官方的代码建立在非常清晰的数学分析的基础之上:

当(rev = rev * 10 + pop) > Integer.MAX_VALUE的时候,溢出就已经发生了。我们需要在溢出发生前返回0这个值。

如果rev * 10 + pop > Integer.MAX_VALUE,rev >= (Integer.MAX_VALUE / 10):

rev > (Integer.MAX_VALUE / 10),肯定会造成overflow;rev == (Integer.MAX_VALUE / 10),则当pop > 7的时候才会造成overflow;

用同样的逻辑来分析当rev < Integer.MIN_VALUE的情况就可以了。

这个问题的一个关键点是,要在溢出发生之前就终止程序,而不是在溢出之后,再来判断rev是否会导致溢出。有很多网友在代码中用到了long这个数据类型。一些人说,题目提到的32-bit环境不应该使用long类型的数据,个人觉得这个说法也不对。毕竟很多网友的答案都通过了。

 

下面,我再给出我自己写的垃圾代码,哈哈哈哈。我写的时候,也没仔细读完题目的说明。最开始有想过,官方答案里面pop和push的这种思路,但后来还是决定把数字转化成string,最后再转化为int(因为我以为转化为string之后,哪怕遇到000321这样的string,最后也能弄成000321的int,实际上还是不可以,题目的说明里面也说了比如input是123000,答案会是321)。

之所以想把自己的代码也贴出来,并记录一下,是因为这个过程中也有学到一些java的基础知识。

class Solution { public int reverse(int x) { if(x == 0 || x == Integer.MIN_VALUE) return 0; int absoluteX = Math.abs(x); String str = ""; while((absoluteX / 10) > 0) { str += String.valueOf(absoluteX % 10); absoluteX /= 10; } str += String.valueOf(absoluteX); if(Long.parseLong(str) > Integer.MAX_VALUE) return 0; else { if(x > 0) return Integer.parseInt(str); else return -Integer.parseInt(str); } } }

我的code很可能仍然有bug。我之所以把x == Integer.MIN_VALUE放在最前面当一个特殊情况处理的原因是:

Math.abs(Integer.MIN_VALUE) == Integer.MIN_VALUE。这一点是我没有想到的。这是Math.abs()的一种特殊情况。

排除这种特殊情况之后,我的思路就是先把x完全转化成string。如果Long.parseLong(str) > Integer.MAX_VALUE,那么就说明会发生溢出,于是返回0。否则根据x的正负,返回相应的值。

再提一个知识点,当我们给一个int类型的变量,赋予一个超过Integer.MAX_VALUE的值,你会发现该变量 == Integer.MIN_VALUE(最小的int负数)。好吧,我真的是觉得很神奇。

https://www.geeksforgeeks.org/integer-max_value-and-integer-min_value-in-java-with-examples/

这道题,转成string就是会更麻烦一些。

 

下面再贴一个其他人的代码:

public class Solution { public int reverse(int x) { long res = 0; for (; x != 0; x /= 10) res = res * 10 + x % 10; return res > Integer.MAX_VALUE || res < Integer.MIN_VALUE ? 0 : (int) res; } }

一些网友争论到底能不能用long,并反驳说如果题目是reverse long type integer,就不能用上面的这种方法了。我也赞同后面部分,但只是针对这道题,个人觉得用long没有什么问题。代码难度会比不用long更小一点。

参考上面的code,我又把自己的code修改了一下,显得更简洁:

class Solution { public int reverse(int x) { if(x == 0 || x == Integer.MIN_VALUE) return 0; int absoluteX = Math.abs(x); String str = ""; for(; absoluteX != 0; absoluteX /= 10) str += String.valueOf(absoluteX % 10); if(Long.parseLong(str) > Integer.MAX_VALUE) return 0; return x > 0 ? Integer.parseInt(str) : -Integer.parseInt(str); } }

 

最新回复(0)