LeetCode 7 整数反转

题目描述

整数反转

给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。

如果反转后整数超过 32 位的有符号整数的范围 [−2^31, 2^31 − 1] ,就返回 0。

假设环境不允许存储 64 位整数(有符号或无符号)。

示例 1:

输入:x = 123
输出:321

示例 2:

输入:x = -123
输出:-321

示例 3:

输入:x = 120
输出:21

示例 4:

输入:x = 0
输出:0

提示:

  • -2^31 <= x <= 2^31 - 1

解法

  1. 转字符串反转

转为字符串后从后往前遍历反转

java代码

java 复制代码
public int revers(int x) {
    String s = String.valueOf(x);
    // 如果第一个是-,则删除,标记有横杠
    boolean hasHyphen = false;
    if (s.charAt(0) == 45) {
      s = s.substring(1);
      hasHyphen = true;
    }

    StringBuilder resBuilder = new StringBuilder();

    // 注意点:1.末尾的0去掉,中间的0保留;2.如果会死负数,把-去掉;2.-2147483648超过了范围,返回0
    // 最后一位是否是0,如果是0,把末尾的0都去掉,遇到第一个非0后,不再去掉0;不是0,则不需要去0
    boolean deleteZero = s.charAt(s.length() - 1) == 48;
    for (int i = s.length() - 1; i > -1; i--) {
      // 如果需要删除0并且遇到了非0,则后面就不再去掉0
      if (deleteZero && s.charAt(i) != 48) {
        deleteZero = false;
      }
      // 如果是0并且需要删除0,则略过
      if (s.charAt(i) == 48 && deleteZero) {
        continue;
      }

      resBuilder.append(s.charAt(i));

    }
    String resString = resBuilder.toString();

    // 判断是否超过范围:负数的话不超过2147483648,整数的话不超过2147483647
    if ((hasHyphen && (resString.length() > 10 || (resString.length() == 10 && resString.compareTo("2147483648") > 0)))
        || (!hasHyphen && (resString.length() > 10 || (resString.length() ==  10 && resString.compareTo("2147483647") > 0)))) {
      return 0;
    }

    int res = "".equals(resString) ? 0 : Integer.parseInt(resString);
    return hasHyphen ? -res: res;
}
  1. 官方解法:数学方法

记rev为翻转后的数字,为完成翻转,我们可以重复「弹出」x 的末尾数字,将其「推入」rev 的末尾,直至 x 为 0。

要在没有辅助栈或数组的帮助下「弹出」和「推入」数字,我们可以使用如下数学方法:

java 复制代码
// 弹出 x 的末尾数字 digit
digit = x % 10
x /= 10

// 将数字 digit 推入 rev 末尾
rev = rev * 10 + digit

题目需要判断反转后的数字是否超过 323232 位有符号整数的范围 [ − 2 31 , 2 31 − 1 ] [-2^{31},2^{31}-1] [−231,231−1]。例如 x = 2123456789 x=2123456789 x=2123456789反转后的 r e v = 9876543212 > 2 31 − 1 = 2147483647 {rev}=9876543212>2^{31}-1=2147483647 rev=9876543212>231−1=2147483647,超过了 323232 位有符号整数的范围。

因此我们需要在「推入」数字之前,判断是否满足:

− 2 31 ≤ r e v ⋅ 10 + d i g i t ≤ 2 31 − 1 -2^{31}≤rev⋅10+digit≤2^{31}-1 −231≤rev⋅10+digit≤231−1

若该不等式不成立则返回 0。

但是题目要求不允许使用 646464 位整数,即运算过程中的数字必须在 323232 位有符号整数的范围内,因此我们不能直接按照上述式子计算,需要另寻他路。

考虑 x>0的情况,记 I N T _ M A X = 2 31 − 1 = 2147483647 {INT\_MAX}=2^{31}-1=2147483647 INT_MAX=231−1=2147483647,由于

则不等式

r e v ⋅ 10 + d i g i t ≤ I N T M A X rev⋅10+digit≤INT_MAX rev⋅10+digit≤INTMAX

等价于

移项得

讨论该不等式成立的条件:

注意到当相等时若还能推入数字,则说明 x 的位数与 INT_MAX的位数相同,且要推入的数字 digit 为 x 的最高位。由于 x 不超过 INT_MAX,因此 digit 不会超过 INT_MAX 的最高位,即 digit≤2。所以实际上当 相等时不等式必定成立。

因此判定条件可简化为:当且仅当小于等于时,就成立。

x<0 的情况类似。

综上所述,判断不等式

− 2 31 ≤ r e v ⋅ 10 + d i g i t ≤ 2 31 − 1 -2^{31}≤rev⋅10+digit≤2^{31}-1 −231≤rev⋅10+digit≤231−1

是否成立,可改为判断不等式

I N T M I N / 10 < = r e v < = I N T M A X / 10 INT_MIN / 10 <= rev <= INT_MAX / 10 INTMIN/10<=rev<=INTMAX/10

java代码:

java 复制代码
class Solution {
    public int reverse(int x) {
        int rev = 0;  // 结果数字
        while (x != 0) {
            if (rev < Integer.MIN_VALUE / 10 || rev > Integer.MAX_VALUE / 10) {
                return 0;
            }
            // 取余数
            int digit = x % 10;
            // 原数字除以10后,得到的商为下一位数字
            x /= 10;
            // 原来的rev*10等于向高位移动一位,再加上余数,就是新数字
            rev = rev * 10 + digit;
        }
        return rev;
    }
}
相关推荐
SomeB1oody3 分钟前
【Rust自学】7.4. use关键字 Pt.2 :重导入与换国内镜像源教程
开发语言·后端·rust
新知图书8 分钟前
Rust编程与项目实战-箱
开发语言·后端·rust
俎树振10 分钟前
深入理解与优化Java二维数组:从定义到性能提升的全面指南
java·算法
SomeB1oody12 分钟前
【Rust自学】7.3. use关键字 Pt.1:use的使用与as关键字
开发语言·后端·rust
DARLING Zero two♡19 分钟前
【优选算法】Sliding-Chakra:滑动窗口的算法流(上)
java·开发语言·数据结构·c++·算法
❦丿多像灬笑话、℡21 分钟前
leetcode 热题100(208. 实现 Trie (前缀树))数组模拟c++
算法·leetcode·c#
minstbe22 分钟前
WEB开发 - Flask 入门:Jinja2 模板语法进阶 Python
后端·python·flask
hjxxlsx22 分钟前
二维数组综合
c++·算法
ylfmsn40 分钟前
线性回归背后的数学
算法·回归·线性回归
无名之逆1 小时前
lombok-macros
开发语言·windows·后端·算法·面试·rust·大学期末