问题描述:
Reverse digits of an integer.
Example1: x = 123, return 321
Example2: x = -123, return -321
原问题链接:https://leetcode.com/problems/reverse-integer/
问题分析
将一个数字倒过来转换,看起来是一个很容易的过程。我们可以定义一个整数result = 0,每次在对输入值取最后一位(remain = x % 10)的时候进行result = result * 10 + remain。当然,考虑到数字的正负问题,我们可以用一个boolean变量来记录。在最开始的时候对数字取绝对值。
按照上述的思路,我们可以很快得到如下的一段代码:
public class Solution {
public int reverse(int x) {
boolean positive = x > 0;
int y = Math.abs(x);
int result = 0;
while(y > 0) {
int remain = y % 10;
result = result * 10 + remain;
y /= 10;
}
return positive ? result : -result;
}
}
看起来一切都挺好的,可是实际上我们运行的时候在一些情况下会出问题,比如说输入数字为1534236469的时候。因为如果我们把这个数字倒过来,它就是9646324351,已经超过int数值所能表示的范围。所以它就导致溢出了。上述代码的一个潜在的问题就是忽略了一点,我们对这个result不断累加的时候它会超过int值范围。所以我们需要考虑一种办法来解决这个问题。
该怎么解决这个问题呢?一种办法就是在代码执行的过程中去判断它是不是接近那个溢出的临界点值。我们取max = Integer.MAX_VALUE / 10。然后再针对当我们取的result的值在某一位的时候是否达到了可以表达的值的上限。这种情况其实比较麻烦,因为我们需要去查这个值为多少,而且是根据正数负数的情况来判断。关键是这个数字要去找,而且也比较容易出错。
其实,还有一种更加简洁有效的方法。上面那个问题的根源是我们进行正数变换的时候导致数字太大了超出了int的范围。而如果我们先用long类型来表示这个数字呢?这样我们做的这种转换是不会导致溢出的。做了转换之后我们需要做的就是再把转换后的数字变成整数。因为是长整数类型,在得到的数字超出整数范围的情况下,我们可以返回0。而对于正常的情况就直接转换成整形就可以了。这样连数字的正负属性都不用考虑。
public class Solution {
public int reverse(int x) {
long answer = 0;
while(x != 0) {
answer = 10 * answer + x % 10;
x /= 10;
}
return (answer > Integer.MAX_VALUE || answer < Integer.MIN_VALUE) ? 0 : (int) answer;
}
}
总结
看似简单的问题也有一些有意思的思路。像这里如果去针对整数类型的范围来判断的话会比较麻烦。而干脆用一个数值表示类型更大的类型来表示,再得到结果后做一些合理的转换。这种方法要简单巧妙不少。