题目:
给出两个整数,计算二者相除的结果,计算过程中不能用乘除和取模操作。如果得到的数字溢出,则返回MAX_INT。
思路一:
将除数的2倍,4倍,8倍……n倍全都存储到一个数组或者列表中,n * 除数 <= 被除数,然后在列表或者数组中从前往后找元素,使得元素<= 被除数,被除数 -= 元素 后,继续往后找,直到被除数小于除数的1倍为止,在期间如果发现被除数变为了0,则停止迭代。
代码一:
import java.util.ArrayList;
import java.util.List;
public class Divide_Two_Integers {
public static int divide(int dividend, int divisor)
{
if(divisor == 0)
return Integer.MAX_VALUE;
if(divisor == - 1 && dividend == Integer.MIN_VALUE)
return Integer.MAX_VALUE;
if(divisor == 1)
return dividend;
if(divisor == -1)
return -dividend;
boolean flag = (dividend < 0 && divisor < 0) || (dividend > 0 && divisor > 0);
int divid = (dividend < 0)?dividend:-dividend;
int divis = (divisor < 0)?divisor:-divisor;
if(divid > divis) return 0;
int result = 0;
int times = 1;
List<Integer> list = new ArrayList<>();
System.out.println(divid);
System.out.println(divis);
while(divid - divis<= divis )
{
times <<= 1;
divis <<= 1;
if(divis <= Integer.MIN_VALUE >> 1)break;
}
int times2 = times;
while(times2 != 1)
{
list.add(divis);
divis >>= 1;
times2 >>= 1;
}
list.add(divis);
int i = 0;
while(i < list.size())
{
if(divid < list.get(i))
{
divid -= list.get(i);
result += times;
}
if(divid == list.get(i))
{
result += times;
break;
}
times >>= 1;
i++;
}
return flag?result:-result;
}
public static void main(String[] args)
{
System.out.println(divide(-2147483648,2));
}
}
时间复杂度:
假设被除数>= n*除数,被除数 < (n+1)*除数,则在链表中存储的元素个数为(int)log(n) + 1(还有元素本身),那么要经过多少次操作才能计算出结果,就要看被除数-n*除数的大小了,最坏情况下,把列表遍历了一遍。所以最坏情况下的时间复杂度,O((int)log(n) + 1)。其实最好情况下,计算n的时候,也要计算(int)log(n) 步。
空间复杂度:
O((int)log(n) + 1)。
思路二:
相当于思路一的简化,并且节省了空间。但是执行步数要多。
代码二:
public class Divide_Two_Integers {
public static int divide(int dividend, int divisor)
{
if(divisor == 0)return Integer.MAX_VALUE;
if(divisor == - 1 && dividend == Integer.MIN_VALUE)return Integer.MAX_VALUE;
if(divisor == 1)return dividend;
if(divisor == -1)return -dividend;
boolean flag = (dividend < 0 && divisor < 0) || (dividend > 0 && divisor > 0);
int result = 0;
long divid = dividend;
divid = Math.abs(divid);
long divis = divisor;
divis = Math.abs(divis);
if(divid < divis) return 0;
while(divid >= divis)
{
long temp = divis;
int times = 1;
while(divid - temp >= temp )
{
temp <<= 1;
times <<= 1;
}
divid -= temp;
result += times;
}
return flag?result:-result;
}
public static void main(String[] args)
{
System.out.println(divide(-2147483648,2));
}
}
时间复杂度:
被除数 = n1 * 除数 + n2 * 除数 + …… nm * 除数 + constant,n1,n2,……nm,均为2的幂。如果nm为1的话,则constant可能不为0。整的计算过程的步骤:logn1+logn2+……lognm,所以时间复杂度就由除数和被除数的关系决定了,由于本人太菜,就不再往下计算了。
空间复杂度:
O(1)。