LeetCode_7_中等_整数反转


1. 题目

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

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

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

示例 1:

输入:x = 123
输出:321

示例 2:

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

示例 3:

输入:x = 120
输出:21

示例 4:

输入:x = 0
输出:0


提示

  • − 2 31 < = x < = 2 31 − 1 -2^{31} <= x <= 2^{31} - 1 231<=x<=2311

2. 思路及代码实现(Python)

2.1 数学方法

rev \textit{rev} rev 为翻转后的数字,为完成翻转,我们可以重复「弹出」 x x x 的末尾数字,将其「推入」 rev \textit{rev} rev 的末尾(最后推入的数字在 x x x 当中是最高位),直至 x x x 0 0 0,此时就完成了数字的反转,反转的操作如下:

rev = 0
    while True:
    	# 弹出x的末尾数字
        digit = x % 10
        # x去掉最后一位
        x //= 10
        # 将x的最后一位压入到rev的末尾
        rev = rev * 10 + digit
        if x == 0:
            break
    return rev

题目中除了反转,还需要判断反转后的数字是否在 − 2 31 , 2 31 -2^{31}, 2^{31} 231,231 之间,因此需要在将 digit 推入 rev 时判断是否满足该范围,若不满足则返回 0。然而,题目给出了另一个限制就是:不允许使用64位整数,如果 digit 推入 rev 超过范围了,则我们先推入后判断的这个思路,就会破坏题目的要求,因此不能直接按照该条件比较大小。

一个思路是,通过公式逆推,判断 digitrev 的取值在什么范围下,推入后的结果满足要求,或者不满足要求。考虑 x > 0 x>0 x>0的情况,记 I N T _ M A X = 2 31 − 1 = 2147483647 INT\_MAX=2^{31}-1=2147483647 INT_MAX=2311=2147483647,显然可得:

I N T _ M A X = ⌊ I N T _ M A X 10 ⌋ × 10 + 7 INT\_MAX=\Big\lfloor \frac{INT\_MAX}{10}\Big\rfloor \times 10+7 INT_MAX=10INT_MAX×10+7

得到:

r e v × 10 + d i g i t ≤ I N T _ M A X rev\times 10 +digit \leq INT\_MAX rev×10+digitINT_MAX

⇒ r e v × 10 + d i g i t ≤ ⌊ I N T _ M A X 10 ⌋ × 10 + 7 \Rightarrow rev\times 10 +digit\leq \Big\lfloor \frac{INT\_MAX}{10}\Big\rfloor\times 10+7 rev×10+digit10INT_MAX×10+7

⇒ ( r e v − ⌊ I N T _ M A X 10 ⌋ ) × 10 ≤ 7 − d i g i t \Rightarrow (rev-\Big\lfloor \frac{INT\_MAX}{10}\Big\rfloor)\times10\leq7-digit (rev10INT_MAX)×107digit

这里的 r e v rev rev ⌊ I N T _ M A X 10 ⌋ \Big\lfloor \frac{INT\_MAX}{10}\Big\rfloor 10INT_MAX 均是整数,而 0 ≤ d i g i t ≤ 9 0\leq digit\leq 9 0digit9,易知:

  1. r e v > ⌊ I N T _ M A X 10 ⌋ rev \gt \Big\lfloor \frac{INT\_MAX}{10}\Big\rfloor rev>10INT_MAX,则上述不等式的左端项至少为 10,而右端项最大为 7,显然不等式不成立;
  2. r e v = ⌊ I N T _ M A X 10 ⌋ rev = \Big\lfloor \frac{INT\_MAX}{10}\Big\rfloor rev=10INT_MAX,上述不等式左端项为0,右端项取值范围为 [ − 2 , 7 ] [-2, 7] [2,7],不等式存在成立的可能;然而,如果等式不成立,说明推入的 d i g i t digit digit x x x 的最高位,因此此时 d i g i t ≤ 2 digit\leq 2 digit2,此时等式成立,这个相悖的条件和结果,说明在该情况下,等式不存在不成立的可能;
  3. r e v < ⌊ I N T _ M A X 10 ⌋ rev \lt \Big\lfloor \frac{INT\_MAX}{10}\Big\rfloor rev<10INT_MAX,上述不等式左端项最大为-10,而右端项的范围是 [ − 2 , 7 ] [-2,7] [2,7],因此,不等式必定成立。

综上可知,当 r e v ≤ ⌊ I N T _ M A X 10 ⌋ rev \leq \Big\lfloor \frac{INT\_MAX}{10}\Big\rfloor rev10INT_MAX时,不等式成立。 x = 0 x=0 x=0,则返回0,而 x < 0 x\lt0 x<0的情况的推导过程与上类似。最终得到,推入末尾数之后是否满足范围要求,可以更改为判断下式是否成立,若不成立,则说明推入末尾数也会超出既定范围,则返回0。

⌊ − 2 31 10 ⌋ ≤ r e v ≤ ⌊ 2 31 − 1 10 ⌋ \Big\lfloor \frac{-2^{31}}{10}\Big\rfloor \leq rev \leq \Big\lfloor \frac{2^{31}-1}{10}\Big\rfloor 10231rev102311

此时,算法的时间复杂度为: O ( l o g ⁡ ∣ x ∣ ) O(log⁡∣x∣) O(logx)。翻转的次数即 x x x 十进制的位数。空间复杂度为: O ( 1 ) O(1) O(1)

class Solution:
    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

执行用时:48 ms
消耗内存:17.06 MB

参考来源:力扣官方题解

  • 26
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值