题目:
给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。
返回被除数 dividend 除以除数 divisor 得到的商。
整数除法的结果应当截去(truncate)其小数部分,例如:truncate(8.345) = 8 以及 truncate(-2.7335) = -2
示例 1:
输入: dividend = 10, divisor = 3
输出: 3
解释: 10/3 = truncate(3.33333..) = truncate(3) = 3
示例 2:
输入: dividend = 7, divisor = -3
输出: -2
解释: 7/-3 = truncate(-2.33333..) = -2
提示:
被除数和除数均为 32 位有符号整数。
除数不为 0。
假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−2^31, 2^31 − 1]。本题中,如果除法结果溢出,则返回 2^31 − 1。
解答:
看了标签为二分法,没有思路,直接看解答:
题目分类提示了二分查找,那么按二分查找的思路去想就行了,既然要求不能使用乘除模运算,那么就让除数不断自加倍增,与被除数对比,倍增过头了就初始化为原始的除数值再次循环倍增,循环过程中被除数减去除数不断减小,直到小于除数为止,其过程就是把二分查找中的 mid = (left + right) / 2 替换成了divisor * 2,把 left 和 right 替换成了 divisor_tmp 和 divideng_tmp,这样理解就比较直观了。
//传进div的值必须是正整数,但是INT_MIN取绝对值会产生溢出问题,所以必须对它采取一定的措施, //即先让它减一次除数或者加一次除数(主要取决于除数的正负号),然后作为被除数的INT_MIN就不会产生溢出问题了。 int divSub(int dividend, int divisor) { if (divisor>dividend) return 0; int res = 1; int original_divisor = divisor; while (dividend - divisor >= divisor)//特别需要注意的地方是dividend-divisor之后还大于等于divisor,即是dividend>=2divisor { divisor += divisor; res += res;//记录被除数是除数的多少倍 } res += divSub(dividend - divisor, original_divisor); return res; } int divide(int dividend, int divisor) { int res = 0; int flag = ((dividend>0 && divisor>0) || (dividend<0 && divisor<0)); //先处理特殊值,即是处理边界溢出问题 INT_MIN if (divisor == 1) return dividend; if (divisor == INT_MIN) return dividend == INT_MIN ? 1 : 0; if (divisor == -1) return dividend == INT_MIN ? INT_MAX : -dividend; if (dividend == INT_MIN)//如果被除数是32位最小整数必须进行一定的处理,先让其减或者加一次除数 { dividend = (flag) ? (dividend - divisor) : (dividend + divisor); res++; } dividend = (dividend>0) ? dividend : -dividend; divisor = (divisor>0) ? divisor : -divisor; res += divSub(dividend, divisor); return (flag) ? res : -res; }
根据上面的思路,自己写了代码,并测试通过:
int divideSub(int dividend, int divisor) { if (divisor > dividend) return 0; int res = 1; int originalDiv = divisor; while (dividend - divisor >= divisor) { divisor += divisor; res += res; } res += divideSub(dividend-divisor, originalDiv); return res; } int divide2(int dividend, int divisor) { if (dividend == 0) return 0; //处理特殊情况 if (divisor == 1) return dividend; else if (divisor == -1) { if (dividend == INT_MIN) { return INT_MAX; } return -dividend; } else if (divisor == INT_MIN) { if (dividend == INT_MIN) return 1; //INT_MIN的值较大,如果被除数是其他值,不够除,则直接返回0 return 0; } //两个参数是否同符号 bool sameSymbol = (dividend > 0 && divisor > 0) || (dividend < 0 && divisor < 0); int res = 0; if (dividend == INT_MIN) //下面递归时,传入的都是正数,INT_MIN传入会溢出,先减或者加上一个除数 { if (sameSymbol) dividend -= divisor; else dividend += divisor; res++; } if (dividend < 0) dividend = -dividend; if (divisor < 0) divisor = -divisor; res += divideSub(dividend, divisor); if (sameSymbol) return res; return -res; }