标签:style blog http io color ar os 使用 java
Divide two integers without using multiplication, division and mod operator.
显然,如果光用减法太慢。让商为N,那么需要用O(N)的时间。这里要求比较苛刻,连乘法都不能使用,所以只能寄希望于二进制操作了。
这里可以把除数表示为:dividend = 2^i * divisor + 2^(i-1) * divisor + ... + 2^0 * divisor。这样一来,我们所求的商就是各系数之和了,而每个系数都可以通过移位操作获得。
这里可以分两步走:
1) 获得i的值;
2)将各系数求和。
显然每步都是logN的复杂度。
外还有几个细节需要注意:
1)题目没有说明两个输入都为正数,所以还需要考虑负数。不过这里不用考虑除数为0的情况。
2)在处理时可能发生整数溢出,不光是在增大数的绝对值,另外反号也可能导致溢出, 因为int的范围为[-2147483648, 2147483647],正负两边的最大绝对值是不一样的。最简单的方法是用long去处理。
代码如下:
- public int divide(int dividend, int divisor) {
- boolean positive = (dividend > 0 && divisor > 0)
- || (dividend < 0 && divisor < 0);
- long absDividend = Math.abs((long) dividend);
- long absDivisor = Math.abs((long) divisor);
-
- int ret = dividePositive(absDividend, absDivisor);
- return positive ? ret : -ret;
- }
-
- private int dividePositive(long dividend, long divisor) {
-
- int i = 0;
- while (dividend >= divisor << 1) {
- divisor <<= 1;
- i++;
- }
-
-
- int ret = 0;
- while (i >= 0) {
- if (dividend >= divisor) {
- dividend -= divisor;
- ret += 1 << i;
- }
- divisor >>= 1;
- i--;
- }
-
- return ret;
- }
另外一种实现可以合并两个循环,边求i的时候,边累加各系数,不过这样没有改变时间复杂度。自己测试了下,发现其实合并循环也不会带来什么实质的性能提升,感觉还是两个循环思路更为清晰。
其实上述方法也可以用递归实现,每次求一个系数,然后对余数进行递归处理。递归代码一般更加精简。
- private int dividePositive(long dividend, long divisor) {
- if (dividend < divisor)
- return 0;
-
- int ret = 1;
- long originalDivisor = divisor;
- while (dividend >= divisor << 1) {
- divisor <<= 1;
- ret <<= 1;
- }
-
- return ret + dividePositive(dividend - divisor, originalDivisor);
- }
补充:
有的时候面试题里是允许使用乘号的,那么其实还可以使用二分搜索。这样中思路类似于LeetCode里的Sqrt(x)。这里注意的问题是,对于非
整除的情况,二分搜索要找到最左边那个乘上divisor后小于dividend的数。这个思路其实类似于在sorted array里找insert
position。
- private int dividePositive(long dividend, long divisor) {
- long low = 0, high = dividend;
- long ret = 0;
- while (low <= high) {
- long mid = low + (high - low) / 2;
- long product = mid * divisor;
- if (product == dividend) {
- return (int) mid;
- } else if (product < dividend) {
- ret = mid;
- low = mid + 1;
- } else {
- high = mid - 1;
- }
- }
-
- return (int) ret;
[LeetCode] Divide Two Integers
标签:style blog http io color ar os 使用 java
原文地址:http://www.cnblogs.com/yuyanbian/p/4088604.html