/**
Divide two integers without using multiplication, division and mod operator.
题目大意:算两个整数相除的结果,不能用乘号、除号、求余号
注意:提供的两个数只限制是整数,可以是正、负、零
**/
public class Solution {
public int divide(int dividend, int divisor) {
//return solve1(dividend, divisor); //违反题意
//return solve2(dividend, divisor); //超时,且不能处理极端数值
return solve3(dividend, divisor);
}
//========================== solve1 =============================
//我偏要直接用除号,来咬我啊~
//想不到居然也Accept了...
private int solve1(int dividend, int divisor){
return dividend / divisor;
}
//========================== solve2 =============================
//既然不能用除号,那就用减号吧
//连乘号都不能用,那就用减号来解决符号问题
//如果出现被除数很大,除数很小,那是一定会超时
//超时之外,这个解法更大的错误在于:当输入最小的那个负数,会导致失败!(最大整数的比最小负数的绝对值要小)
private int solve2(int dividend, int divisor){
int result = 0;
//记住最后的符号
int mult = -1;
if((dividend>=0 && divisor>=0)
|| (dividend<0 && divisor<0))
mult = 1;
//全部变成正的
//在这里,如果输入的是-2147483648,那就肯定会出错,因为对于int来说,这个数字是没有正数的
if(dividend < 0)
dividend = 0 - dividend;
if(divisor < 0)
divisor = 0 - divisor;
//用减号求商
while(dividend >= divisor){
dividend -= divisor;
result++;
}
//确定符号
if(mult == -1)
result = 0 - result;
return result;
}
//========================== solve3 =============================
//其实这里采取的也是除数一点点往上加,看什么时候能加到最接近被除数的时候,答案就出来了
//只不过先从最大可能的那个数开始加,减少加的次数,降低操作次数
//这类题重点在于,从一开始就必须要进行类型转换,变成long,否则对于极端数值没法操作
private int solve3(int dividend, int divisor){
//一开始就转换成long
long div1 = (long)dividend;
long div2 = (long)divisor;
//记住最后的符号
int mult = -1;
if((div1>=0 && div2>=0)
|| (div1<0 && div2<0))
mult = 1;
//全部变成正的
if(div1 < 0)
div1 = 0 - div1;
if(div2 < 0)
div2 = 0 - div2;
//存放被除数的倍数的数组,由于是int,最多不可能超过2^32
long[] numbers = new long[33];
//存放倍数本身
long[] times = new long[33];
long time = 1L;
int num = 0;
//存入当前除数,作为单倍体
numbers[num] = div2;
times[num] = time;
num++;
//将除数的各种2的倍数存好,直到超过被除数
while(div2 <= div1){
div2 = div2 + div2;
time = time + time;
if(div2 <= div1){
numbers[num] = div2;
times[num] = time;
num++;
}
}
//用存储好的数加起来,看加多少可以加到被除数
long sumUp = 0L;
long timeUp = 0L;
for(int i=num-1; i>=0; i--){
//这种是可以整除的情况
if(sumUp == div1)
break;
//从除数的最大可能倍数一直到除数本身
//最大限度的缩减需要加的次数
while(sumUp+numbers[i] <= div1){ //注意这里的等号,是必须要的
sumUp += numbers[i];
timeUp += times[i];
}
}
if(mult == -1)
timeUp = 0 - timeUp;
return (int)timeUp;
}
}
LeetCode:Divide Two Integers
最新推荐文章于 2017-11-23 20:34:00 发布