LeetCode #7 Medium

整数反转

更新于:2026-01-27 在 LeetCode 上查看

题目描述

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

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

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

示例

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

思路分析

方法一:字符串反转法(直观但非最优)

最直观的想法是将数字转为字符串,反转后再转回数字:

  1. 处理符号位
  2. 取绝对值转字符串
  3. 反转字符串
  4. 转回数字并恢复符号
  5. 检查是否溢出

这种方法简单易懂,但存在以下问题:

  • 需要额外的字符串空间
  • 多次类型转换效率较低
  • 不符合”不使用 64 位整数”的题目要求(JavaScript 的 Number 是 64 位浮点数)

方法二:数学取模法(巧妙且高效)⭐

通过数学运算逐位提取并构建反转数字,这是最优解法。

核心思想:

  • x % 10 获取当前最后一位数字
  • x / 10 去掉最后一位
  • result * 10 + digit 将数字添加到结果的末尾

为什么巧妙:

  1. 负数处理的妙用

    • 在 JavaScript 中,-123 % 10 = -3 (保留符号)
    • 这意味着负数可以和正数用完全相同的逻辑处理,无需单独判断符号!
  2. 位运算截断的技巧

    • (x / 10) | 0 相当于 Math.trunc(x / 10)
    • |0 会将浮点数转为 32 位有符号整数并截断小数部分
    • Math.floor() 更快,且对正负数都有效
  3. 溢出检测的精妙之处

    • (result | 0) === result 是溢出检测的关键
    • 如果 result 超出 32 位整数范围,|0 操作会将其截断/溢出
    • 截断后的值与原值不相等,说明发生了溢出
    • 这种方法无需显式比较边界值,简洁高效
  4. 空间复杂度优化

    • 完全通过数学运算实现,不需要字符串或数组等额外空间
    • 只用了几个变量,空间复杂度 O(1)

代码实现

字符串反转法

function reverse(x: number): number {
  const isNegative = x < 0;
  const reversedStr = Math.abs(x).toString().split("").reverse().join("");
  const reversedNum = isNegative ? -Number(reversedStr) : Number(reversedStr);

  // 检查是否超出 32 位有符号整数范围
  const INT_MAX = Math.pow(2, 31) - 1;
  const INT_MIN = -Math.pow(2, 31);

  if (reversedNum < INT_MIN || reversedNum > INT_MAX) {
    return 0;
  }

  return reversedNum;
}

数学取模法(推荐 · 参考他人思路)⭐

function reverse(x: number): number {
  let result = 0;

  while (x !== 0) {
    // 提取最后一位数字(负数会保留负号)
    const digit = x % 10;

    // 构建反转后的数字
    result = result * 10 + digit;

    // 去掉最后一位(使用位运算截断小数)
    x = (x / 10) | 0;
  }

  // 溢出检测: 如果 result 超出 32 位整数范围,|0 会导致值改变
  return (result | 0) === result ? result : 0;
}

执行流程示例

x = -123 为例:

循环x 初始值digit (x%10)result 计算x 更新 ((x/10)|0)
1-123-30×10 + (-3) = -3-12
2-12-2-3×10 + (-2) = -32-1
3-1-1-32×10 + (-1) = -3210
结束0--321-

溢出检测: (-321 | 0) === -321 → true,返回 -321