给你一个 32 位的有符号整数 x
,返回将 x
中的数字部分反转后的结果。
如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1]
,就返回 0。
假设环境不允许存储 64 位整数(有符号或无符号)。
示例 1:
输入:x = 123
输出:321
示例 2:
输入:x = -123
输出:-321
示例 3:
输入:x = 120
输出:21
示例 4:
输入:x = 0
输出:0
提示:
-231 <= x <= 231 - 1
记 r e v rev rev 为翻转后的数字,为完成翻转,我们可以重复「弹出」 x x x 的末尾数字,将其「推入」 r e v rev rev 的末尾,直至 x x x 为 0。
要在没有辅助栈或数组的帮助下「弹出」和「推入」数字,我们可以使用如下数学方法:
// 弹出 x 的末尾数字 digit
digit = x % 10
x /= 10
// 将数字 digit 推入 rev 末尾
rev = rev * 10 + digit
题目需要判断反转后的数字是否超过 32 位有符号整数的范围 [ − 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,超过了 32 位有符号整数的范围。
因此我们需要在「推入」数字之前,判断是否满足
− 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
若该不等式不成立则返回 000。
但是题目要求不允许使用 64 位整数,即运算过程中的数字必须在 32 位有符号整数的范围内,因此我们不能直接按照上述式子计算,需要另寻他路。
考虑 x > 0 x>0 x>0 的情况,记 I N T M A X = 2 31 − 1 = 2147483647 INT_MAX=2^{31}−1=2147483647 INTMAX=231−1=2147483647,由于
INT_MAX = ⌊ INT_MAX 10 ⌋ ⋅ 10 + ( INT_MAX m o d 10 ) = ⌊ INT_MAX 10 ⌋ ⋅ 10 + 7 \begin{aligned} \textit{INT\_MAX}&=\lfloor\dfrac{\textit{INT\_MAX}}{10}\rfloor\cdot10+(\textit{INT\_MAX}\bmod10)\\ &=\lfloor\dfrac{\textit{INT\_MAX}}{10}\rfloor\cdot10+7 \end{aligned} INT_MAX=⌊10INT_MAX⌋⋅10+(INT_MAXmod10)=⌊10INT_MAX⌋⋅10+7
则不等式
rev ⋅ 10 + digit ≤ INT_MAX \textit{rev}\cdot10+\textit{digit}\le\textit{INT\_MAX} rev⋅10+digit≤INT_MAX
等价于
r e v ⋅ 10 + d i g i t ≤ ⌊ I N T _ M A X 10 ⌋ ⋅ 10 + 7 rev⋅10+digit≤⌊INT\_MAX10⌋⋅10+7 rev⋅10+digit≤⌊INT_MAX10⌋⋅10+7
移项得
( r e v − ⌊ I N T _ M A X 10 ⌋ ) ⋅ 10 ≤ 7 − d i g i t (rev−⌊INT\_MAX10⌋)⋅10≤7−digit (rev−⌊INT_MAX10⌋)⋅10≤7−digit
讨论该不等式成立的条件:
若 r e v > ⌊ I N T _ M A X 10 ⌋ rev>⌊INT\_MAX10⌋ rev>⌊INT_MAX10⌋,由于 d i g i t ≥ 0 digit≥0 digit≥0,不等式不成立。 若 r e v = ⌊ I N T _ M A X 10 ⌋ rev=⌊INT\_MAX10⌋ rev=⌊INT_MAX10⌋,当且仅当 d i g i t ≤ 7 digit≤7 digit≤7 时,不等式成立。 若 r e v < ⌊ I N T _ M A X 10 ⌋ rev<⌊INT\_MAX10⌋ rev<⌊INT_MAX10⌋,由于 d i g i t ≤ 9 digit≤9 digit≤9,不等式成立。
注意到当 r e v = ⌊ I N T _ M A X 10 ⌋ rev=⌊INT\_MAX10⌋ rev=⌊INT_MAX10⌋ 时若还能推入数字,则说明 x x x 的位数与 I N T _ M A X INT\_MAX INT_MAX 的位数相同,且要推入的数字 d i g i t digit digit 为 x x x 的最高位。由于 x x x 不超过 I N T _ M A X INT\_MAX INT_MAX,因此 d i g i t digit digit 不会超过 I N T _ M A X INT\_MAX INT_MAX 的最高位,即 d i g i t ≤ 2 digit≤2 digit≤2。所以实际上当 r e v = ⌊ I N T _ M A X 10 ⌋ rev=⌊INT\_MAX10⌋ rev=⌊INT_MAX10⌋ 时不等式必定成立。
因此判定条件可简化为:当且仅当 r e v ≤ ⌊ I N T _ M A X 10 ⌋ rev≤⌊INT\_MAX10⌋ rev≤⌊INT_MAX10⌋ 时,不等式成立。
x < 0 x<0 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
是否成立,可改为判断不等式
⌈ − 2 3 1 10 ⌉ ≤ r e v ≤ ⌊ 2 31 − 1 10 ⌋ ⌈\frac{−2^31}{10}⌉≤ rev ≤⌊\frac{2^{31}−1}{10}⌋ ⌈10−231⌉≤rev≤⌊10231−1⌋
是否成立,若不成立则返回 0。
def reverse(self, x: int) -> int:
INT_MIN, INT_MAX = -2**31, 2**31 - 1
rev = 0
while x != 0:
# INT_MIN 也是一个负数,不能写成 rev < INT_MIN // 10
if rev < INT_MIN // 10 + 1 or rev > INT_MAX // 10:
return 0
digit = x % 10
# Python3 的取模运算在 x 为负数时也会返回 [0, 9) 以内的结果,因此这里需要进行特殊判断
if x < 0 and digit > 0:
digit -= 10
# 同理,Python3 的整数除法在 x 为负数时会向下(更小的负数)取整,因此不能写成 x //= 10
x = (x - digit) // 10
rev = rev * 10 + digit
return rev
int reverse(int x)
{
int rev = 0;
while (x != 0)
{
if (rev < INT_MIN / 10 || rev > INT_MAX / 10)
{
return 0;
}
int digit = x % 10;
x /= 10;
rev = rev * 10 + digit;
}
return rev;
}