这是力扣上的一道题目,难度为中等
1、题目描述
给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。
2、题解效果
3、题解思路
举个栗子:11除以2
11先与2比大小,发现比2大,则将除数翻倍(加一次自己),结果1也翻倍,然后试试有没有比11大,不比11大就再翻倍,过程则变成(除数:2→4→8 结果1→2→4),到了除数为16时发现比11大了,就不要再翻倍了,除数依然设置成8且此时结果为4。
到这里时,再用11减去8,等于3,再去算3除以2的值,此时题目就变成了算3除以2,跟上面方法相同,算出来结果为1,此时题目变成1除以2,1小于2,结果为0。再把所有的结果加起来,4+1+0=5
再举个栗子:举个例子:11 除以 3 。
首先11比3大,结果至少是1, 然后让3翻倍,就是6。(结果也从1翻倍到2)
但发现11还是大于6,那我让这个6再翻倍,得12,11不比12大,吓死我了,差点让最小解2也翻倍得到4了。但是我知道最终结果肯定在2和4之间。也就是说2再加上某个数,这个数是多少呢?我让11减去刚才最后一次的结果6,剩下5,我们计算5是3的几倍,也就是除法,看,递归出现了。
在纸上画一画,模拟几遍就懂了,实在不行看代码吧!
4、代码
class Solution {
public int divide(int dividend, int divisor) {
if(dividend == 0) return 0;//0除以所有数为0
if(divisor == -1){
if(dividend>Integer.MIN_VALUE) return -dividend;// 只要不是最小的那个整数,都是直接返回相反数就好啦
return Integer.MAX_VALUE;// 是最小的那个,那就返回最大的整数啦
}
int symFlag=1;//symFlag用于处理正负号的问题,如果两者同号,则为1,结果为正,异号,则为0,结果为负
long longDividend = dividend;//转为long型是因为部分测试用例很刁钻
long longDivisor= divisor;
//把负的除数和负的被除数都转成正的便于计算,用symFlag处理正负号的问题
if(longDividend<0){
symFlag=-symFlag;
longDividend=-longDividend;
}
if(longDivisor<0){
symFlag=-symFlag;
longDivisor=-longDivisor;
}
if(symFlag<0)
return -divideFunc(longDividend,longDivisor);
else
return divideFunc(longDividend,longDivisor);
}
public int divideFunc(long dividend,long divisor){
if(dividend<divisor)
return 0;
if(dividend==divisor)
return 1;
long tmpDivisor=divisor;
long res=1;
while(dividend>(tmpDivisor+tmpDivisor)){
res=res+res;
tmpDivisor=tmpDivisor+tmpDivisor;
}
return (int)res+divideFunc(dividend-tmpDivisor,divisor);
}
}