LEETCODE注解
29:两数相除
给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。
返回被除数 dividend 除以除数 divisor 得到的商。
说明:
被除数和除数均为 32 位有符号整数。
除数不为 0。
假设我们的环境只能存储 32 位有符号整数,其数值范围是int [min, max]。
本题中,如果除法结果溢出,则返回 int最大值
解法一:最容易想到的是做减法。
减法容易遇到的问题:
1.除数与被除数符号问题,会有四种情况(++,±,-+,–)比较麻烦。解决方法将除数与被除数都转化成负数或正数。
转化正数出现的问题:dividend=int类型最小值时,转化成正数会溢出问题。因此,决定dividend与divisor都转化成负数。
2.结果溢出问题。只存在dividend=Integer.MIN_VALUE && divisor=-1这一种情况。因此单独处理。
代码如下:
class Solution {
public int divide(int dividend, int divisor) {
if(dividend==Integer.MIN_VALUE && divisor==-1) return Integer.MAX_VALUE;
int x = dividend ;
int y = divisor ;
if(x > 0) x = -x;
if(y > 0 ) y = -y;
if(x > y) return 0;
int flag = 0;
if(dividend>0&&divisor<0 || dividend<0&&divisor>0) flag = 1;
int count = 0;
while(x <= y)
{
x = x - y;
count++;
}
if(flag==0) return count;
else return -count;
}
}
但显而易见这种方法的最大问题速度太慢,超出时间限制。因此需要第二种解法。
解法二:既然一个一个减去太慢,那让减得越来越多。
例如:
15 2 0
13 4 0+1=1
9 8 0+1+2=3
1 16 0+1+2+4=7
1 2 算出结果
代码如下
class Solution {
public int divide(int dividend, int divisor) {
if(dividend==Integer.MIN_VALUE && divisor==-1) return Integer.MAX_VALUE;
int x = dividend ;
int y = divisor ;
if(x > 0) x = -x;
if(y > 0 ) y = -y;
int disy = y;
if(x > y) return 0;
int flag = 0;
if(dividend>0&&divisor<0 || dividend<0&&divisor>0) flag = 1;
int count = 0;
int multiple = 1;
while(x <= disy)
{
if(x-y<=0)
{
x = x - y;
y += y;//翻倍减少
count += multiple;
multiple += multiple;//翻倍增加
}
else//y重新归到初始值
{
y = disy;
multiple = 1;
}
}
if(flag==0) return count;
else return -count;
}
}
正如代码所示,每过一轮,y翻倍,multiple翻倍增加。等价于2的n次方*y的速度减少。直到剩余x小于当前y时,y值重新回到初始值divisor。重新进行循环。