持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第13天,点击查看活动详情
解题思路
容易想到的思路是直接相减,被除数减去除数,然后看减了多少次就是题目的解,但是假设被除数是Math.pow(2, 30),而除数是1,那么时间复杂度就是O(n)了 思路是:当被除数大于除数时,继续判断被除数是否大于除数的2倍,如果是,则继续判断被除数是否大于除数的4倍、8倍、16倍等;如果被除数最多大于除数的2的k次方,那么将被除数减去除数的2的k次方,然后将剩余的被除数重复前面的步骤; 举例来说:15大于2,也大于2的2倍(2的2次方也就是4),还大于2的4倍(2的3次方也就是8),但是小于2的8倍(2的4次方也就是16),先将15减去8(减去这部分对应的商是4),还剩余7 接下来比较7和除数2,7最多大于2的2倍(也就是4),因为7小于2的4倍(也就是8),将7减去4(减去这部分对应的商是2),还剩余3 3大于2但小于2的2倍(也就是4),所以将3减去2(减去这部分对应的商是1),还剩余1.比除数小,不能再减去除数了 所以15/4的商是4+2+1,也就是7 时间复杂度是O(logn)
代码
/**
* @param {number} dividend
* @param {number} divisor
* @return {number}
*/
var divide = function(dividend, divisor) {
// 因为最大的整数为2的31次方减去1,而最小的整数负2的31次方
// 按照两个负数去算就会超出正数的范围,会导致溢出,需特殊处理
if (dividend === -Math.pow(2, 31) && divisor === -1) {
return Math.pow(2, 31) - 1;
}
// 正负号
let negative = 2;
// 如果有正数,则可以将它们先转换成负数,计算负数的除法之后再根据需要调整商的正负号
if (dividend > 0) {
negative--;
dividend = -dividend;
}
if (divisor > 0) {
negative--;
divisor = -divisor;
}
const divideCore = (dividend, divisor) => {
let result = 0;
while (dividend <= divisor) {
let value = divisor;
let quatient = 1;
while (
// 最小的整数是-2的31次方,而最大的整数是2的31次方减1
value >= -Math.pow(2, 30) &&
dividend <= value + value
) {
// 当被除数大于除数时,继续判断被除数是否大于除数的2倍
// 如果是,则继续判断被除数是否大于除数的4倍、8倍、16倍等
quatient += quatient;
value += value;
// 这里以a为15,b为2举例,
// quatient为1+1=2,value=2+2=4;quatient为2+2=4,value=4+4=8;quatient为4+4=8,value=8+8=16;
}
result += quatient;
dividend -= value;
}
return result;
};
let result = divideCore(dividend, divisor);
return negative == 1 ? -result : result;
};