整数反转
leetcode 7
反转一个 32 位的有符号整数,取值范围是 [ − 2 31 , 2 31 − 1 ] [−2^{31}, 2^{31} − 1] [−231,231−1],若溢出,返回 0。
两种方式解决此问题:
- 转换法。
- 数学方法。
转换法
通过转换为字符串或列表进行翻转,得到结果。
通过转换成列表,使用列表内置函数 list.reverse()
,再转换回去。(不推荐)
# int --> str --> list --> int
def reverse(x: int) -> int:
def change(x):
nums = list(str(x))
nums.reverse()
return int(''.join(nums))
if x >= 0:
if change(x) > 2**31-1:
return 0
return change(x)
if -change(-x) < -2**31:
return 0
return -change(-x)
或转换为 str
,利用切片反转。(推荐)
# int --> str --> int
def reverse(x: int) -> int:
sign = 1 if x > 0 else -1
x = x if x > 0 else -x
res = sign * int(str(x)[::-1])
if - 2 ** 31 < res < 2 ** 31 - 1:
return res
return 0
注意:字符串转换的效率较低且使用较多库函数,会导致很慢。整体来说,不如使用数学方法。
数学法
通过正数的不断求余,整除,得到数的反序。
可以将待反转的数字当成一个栈,出栈后进入一个新的栈。
这样理解比从数学取整取余的操作直观一些。
如下图,123 转换为 321。
def reverse(x: int) -> int:
sign = 1 if x > 0 else -1
x = x if x > 0 else -x
res = 0
while x:
res = res * 10 + x % 10
x //= 10
res = sign * res
if - 2 ** 31 < res < 2 ** 31 - 1:
return res
return 0
时间复杂度是: O ( log n ) O(\log n) O(logn)。对于每次迭代,我们会将输入除以 10,因此时间复杂度为 O ( log n ) O(\log n) O(logn)。
x
相当于原始栈,res
是新的栈。
判空:x != 0
x
出栈并更新:pop = x % 10
、x //= 10
res
入栈并更新:res = res * 10 + x % 10
扩展:Python 取整取余操作
对于两个正数,和我们所熟知的计算完全相同。
对于负数运算,可能会和日常理解有偏差。
这是因为:
- Python 中的
//
结果向下取整。
print(7 // 3) # 2.3333333...... # 向下取整为 2
print(-7 // 3) # -2.333333..... # 向下取整为 3
print(7 // -3) # -2.333333...... # 向下取整为 3
print(3 // 7) # 0.42.. # 向下取整为 0
print(-3 // 7) # -1
print(3 // -7) # -1
%
的结果根据//
的结果得来。
print(7 % 3) # 1 # 整数取 2 余 1
print(-7 % 3) # 2 # 整数取 -3 余 2
print(7 % -3) # -2 # 整数取 -3 余 -2
print(3 % 7) # 3
print(-3 % 7) # 4
print(3 % (-7)) # -4
对于负数计算余数和取整要多加注意。