给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。git
返回被除数 dividend 除以除数 divisor 获得的商。github
示例 1:bash
输入: dividend = 10, divisor = 3
输出: 3
复制代码
示例 2:ide
输入: dividend = 7, divisor = -3
输出: -2
复制代码
说明:ui
解题思路来自评论区的foxleezh大神。题目中明确不能使用/
, 咱们能够右移模拟除法,右移能够等价于下面的等式spa
a / 2 === a >> 1
a / 4 === a >> 2
a / 8 === a >> 3
复制代码
被除数 / 除数 === 商……余数
等价于 ➡️ 被除数 === (商 * 除数) + 余数
等价于 ➡️ (被除数 - 余数) / 商 === 除数
code
假设,咱们的被除数等于100,除数等于5。get
根据等式(被除数 - 余数) / 商 == 除数
,咱们首先要找到,100除以多少最接近于除数(或者说,除以多少时会大于等于除数)。it
当100除以2^31时,结果相较于除数会很是的小。咱们使用循环逐渐减小右移的位数,逐渐逼近除数,当100 >>> 4(100 / 16)时等于6,大于等于5。io
这时,咱们能够确定**商是大于16(2的四次方)**的某个数(或者说,100至少包含16个5)。
咱们使用被除数 = 被除数 - 16 * 除数
等于还剩下的没有除干净的数。目前还剩下20。咱们再次使用上述的方法,再次逼近除数(获取20里还有几个5)。最终获得最后的结果。
/** * @param {number} dividend * @param {number} divisor * @return {number} */
var divide = function(dividend, divisor) {
// 判断结果是否为负数
const isNegative = (dividend ^ divisor) < 0
// 统一按正数处理
dividend = Math.abs(dividend)
divisor = Math.abs(divisor)
if (dividend === 0) {
return 0
}
if (dividend === 2147483648 && divisor === 1) {
// 避免结果溢出
return isNegative ? -dividend/divisor : dividend/divisor - 1
}
let result = 0
for (let i = 31; i >= 0; i--) {
// 注意这里须要使用无符号右移
if ((dividend >>> i) >= divisor) {
result += Math.pow(2, i)
dividend -= Math.pow(2, i) * divisor
}
}
return isNegative ? -result : result
};
复制代码