7. 整数反转

题目

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

示例

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

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

示例 3: 输入: 120 输出: 21

注意

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

我的方案

利用StringBuffer 做中间装换

Java源码

class Solution {
    public int reverse(int x) {
        if (x > -10 && x < 10) {
            return x;
        }
        long subFlag = x < 0 ? -1l : 1l;
        StringBuffer buffer = new StringBuffer().append(x * subFlag);
        long y = Long.valueOf(buffer.reverse().toString()) * subFlag;
        if (y > Integer.MAX_VALUE || y < Integer.MIN_VALUE)
            return 0;
        return (int) (y);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

Dart源码

final num MAX_VALUE = pow(2, 31) - 1;
  final num MIN_VALUE = -pow(2, 31);
  if (x > -10 && x < 10) {
    return x;
  }
  num subFlag = x < 0 ? -1 : 1;
  String str = (x * subFlag).toString();
  int length = str.length;
  StringBuffer buffer = new StringBuffer();
  while (length > 0) {
    buffer.write(str.substring(length - 1, length));
    length--;
  }

  num y = num.parse(buffer.toString()) * subFlag;
  if (y > MAX_VALUE || y < MIN_VALUE) return 0;
  return y.toInt();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

推荐方案

我们可以一次构建反转整数的一位数字。在这样做的时候,我们可以预先检查向原整数附加另一位数字是否会导致溢出。

  1. 不考虑使用辅助变量类型的情况下,我们可以使用数学方法。
// 循环计算,直到全部推出为止
while
// 求个位数字:
pop = x % 10;
// 将个位推出
x /= 10;
// 计算转换后的数
rev = rev * 10 + pop;
1
2
3
4
5
6
7
8
  1. 关键一步在理解 temp = rev * 10 + pop; 的取值过程,我们不妨将他转换成一个不等式的解答。

题目

已知 MAX = 2147483647,MIN = -2147483648, f(rev,pop) = rev * 10 + pop, 且 rev 和 pop都为整数,且 -9 <= pop <= 9, 求 rev和pop在什么条件下 MIN <= f(rev,pop) <= MAX ;

解题

MIN <= f(rev,pop) <= MAX 等价于 !(f(rev,pop)>MAX || f(rev,pop)<MIN);

我们分析两个临界点即可

  1. 高于 MAX 的情况

rev * 10 + pop > MAX 时,对与rev来说,分以下3种情况:

  1. rev < MAX / 10;∵ 是取整,所以 rev <= 214748363,而 pop <= 9, ∴ f(rev,pop)<=2147483639 < MAX,符合条件 。   2. rev = MAX / 10;∵ 是取整,所以 rev = 214748364, ∴ pop <=7 时 f(rev,pop) 符合条件,pop>7 时,不符合条件。   3. rev > MAX / 10;∵ 是取整,所以 rev >= 214748365,∴ f(rev,pop) 不符合条件

  1. 低于 MIN 的情况

rev * 10 + pop < MIN 时,对于rev来说,也分以下3中情况讨论:

  1. rev < MIN / 10; ∵ 是取整,所以 rev <= -214748365,f(rev,pop) 不符合条件

  2. rev = MIN / 10; ∵ 是取整,所以 rev = -214748364, ∴ pop >= -8 时 f(rev,pop) 符合条件,pop < -8 时,不符合条件

  3. rev > MIN / 10; ∵ 是取整,所以 rev >= -214748363,而 pop >= -9, ∴ f(rev,pop)>= -2147483639 > MIN,符合条件 。

总结 当 (rev < MAX / 10 && rev > MIN / 10) || (rev = MAX / 10 && pop < 8) || (rev = MIN / 10 && pop > -9) 时,MIN <= f(rev,pop) <= MAX ;

Java源码

class Solution {
    public int reverse(int x) {
        if (x > -10 && x < 10) {
            return x;
        }
        int rev = 0;
        while (x != 0) {
          int pop = x % 10;
          x = 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;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

Dart源码

int reverse(int x) {
    if (x > -10 && x < 10) {
        return x;
    }   
    final num MAX_VALUE = pow(2, 31) - 1;
    final num MIN_VALUE = -pow(2, 31);
    int rev = 0;
    while (x != 0) {
        int pop = x % 10;
        x = (x ~/ 10).toInt();
        if (rev > MAX_VALUE / 10 || (rev == MAX_VALUE / 10 && pop > 7)) return 0;
        if (rev < MIN_VALUE / 10 || (rev == MIN_VALUE / 10 && pop < -8)) return 0;
        rev = rev * 10 + pop;
    }
    return rev;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
最后更新时间: 10/15/2019, 4:29:26 PM