题目
题目描述
给你两个整数,被除数 dividend 和除数 divisor。将两数相除,要求 不使用 乘法、除法和取余运算。
整数除法应该向零截断,也就是截去(truncate)其小数部分。例如,8.345 将被截断为 8 ,-2.7335 将被截断至 -2 。
返回被除数 dividend 除以除数 divisor 得到的 商 。
注意:假设我们的环境只能存储 32 位 有符号整数,其数值范围是 [−231, 231 − 1] 。本题中,如果商 严格大于 231 − 1 ,则返回 231 − 1 ;如果商 严格小于 -231 ,则返回 -231 。
示例 1:
输入: dividend = 10, divisor = 3
输出: 3
解释: 10/3 = 3.33333… ,向零截断后得到 3 。
示例 2:
输入: dividend = 7, divisor = -3
输出: -2
解释: 7/-3 = -2.33333… ,向零截断后得到 -2 。
提示:
-2^31 <= dividend, divisor <= 2^31 - 1
divisor != 0
题目链接
题解
解题思路
为了实现这个不使用乘法、除法和取余运算的整数除法,我们可以使用减法和位移操作来完成。基本思路是不断地从被除数中减去除数,并记录减去了多少次,这将给出商的绝对值。考虑到正负号问题,我们还需要跟踪最终结果的符号。
另外,由于题目要求考虑32位有符号整数的溢出情况,我们需要在返回结果之前检查是否超出了 [−2^31, 2^31 − 1]
的范围。
python实现
下面是一个 Python 函数的实现:
def divide(dividend: int, divisor: int) -> int:
# 处理可能的溢出情况
INT_MAX = 2**31 - 1
INT_MIN = -2**31
# 特殊情况处理:如果被除数为0,直接返回0
if dividend == 0:
return 0
# 计算结果的符号
sign = -1 if (dividend > 0 and divisor < 0) or (dividend < 0 and divisor > 0) else 1
# 将被除数和除数都转换成正数进行处理
dividend, divisor = abs(dividend), abs(divisor)
# 结果初始化
result = 0
# 当被除数大于等于除数时,执行循环
while dividend >= divisor:
temp, multiple = divisor, 1
# 使用位移操作加速查找
while dividend >= (temp << 1):
temp <<= 1
multiple <<= 1
# 减去当前找到的最大倍数的除数,并更新结果
dividend -= temp
result += multiple
# 根据符号调整最终的结果,并检查是否溢出
result = result if sign > 0 else -result
if result > INT_MAX:
return INT_MAX
elif result < INT_MIN:
return INT_MIN
else:
return result
代码解释
上述代码首先处理了一些特殊情况,如被除数为0的情况。然后它通过位移操作加速了查找过程,每次尝试将除数翻倍(即左移一位),直到不能再大为止。接着它从被除数中减去这个最大倍数的除数,并增加相应的倍数到结果中。最后根据最初的符号确定结果的正负,并检查是否有溢出。
这种方法避免了直接使用乘法、除法或取余运算,同时保持了较高的效率。