Divide Two Integers
Divide two integers without using multiplication, division and mod operator.
方法一:暴力破解,不断用被除数减去除数,直至出现负数停止,铁定超时。
方法二:对方法一的改进,每次寻找 满足2k-1 * 除数 <= 被除数 < 2k * 除数第一个k,那么被除数直接减去 2k-1 个除数,同时积累商值,更新被除数
需要注意溢出的问题。
1 class Solution { 2 public: 3 int divide(int dividend, int divisor) { 4 bool minus = false; 5 if( (dividend>0 && divisor<0) || (dividend<0 && divisor>0) ) minus = true; //判断正负 6 long long divd = abs((long long)dividend); //防止溢出 7 long long divs = abs((long long)divisor); 8 long long ans = 0; 9 while( divd >= divs ) { //如果被除数依然大于除数,表明可以继续减 10 long long tmp = divs; 11 int i=0; 12 while( tmp <= divd ) { //寻找第一个满足2k-1 * 除数 <= 被除数 < 2k * 除数的k 13 tmp <<= 1; 14 ++i; 15 } 16 ans += 1<<(i-1); //积累商值 17 divd -= tmp>>1; //被除数更新 18 } 19 return minus ? -ans : ans; 20 } 21 };
方法三:二分搜索商值,可以确定商值在[0,被除数]之间,因此可以在这区间不断进行二分搜索,由于不能使用乘法,除法,取模操作,那么计算 商*除数的 运算修改为加、减、移位操作,即multic * num = multic 为偶数,multic/2 * num * 2 或 multic 为奇数,multic/2 * num * 2 + num,那么时间复杂度就为O(lognlogn)
1 class Solution { 2 public: 3 int divide(int dividend, int divisor) { 4 bool minus = false; 5 if( (dividend>0 && divisor<0) || (dividend<0 && divisor>0) ) minus = true; 6 long long divd = abs((long long)dividend); 7 long long divs = abs((long long)divisor); 8 long long ans = 0; 9 long long left = 0, right = divd; //确定搜索区间 10 while( left <= right ) { 11 long long mid = left + ( (right-left) >> 1 ); //取中 12 long long tmp = multiple(mid, divs); //计算mid * 除数 13 if( tmp == divd ) { //如果乘后的值等于被除数 14 ans = mid; 15 break; 16 } 17 if( tmp < divd ) { //如果乘后值小于,那么应该增大商 18 ans = mid; 19 left = mid+1; 20 } 21 else right = mid-1; //否则减少商 22 } 23 return minus ? -ans : ans; 24 } 25 26 long long multiple(long long multic, long long num) { //分治法求a*b 27 if( multic == 0 ) return 0; 28 long long ans = multiple(multic>>1, num) << 1; //先求a/2 * b,在将值乘2 29 if( multic & 1 ) ans += num; //如果a为奇数 30 return ans; 31 } 32 };