码迷,mamicode.com
首页 > 其他好文 > 详细

[LeetCode] Divide Two Integers

时间:2014-11-11 02:02:27      阅读:214      评论:0      收藏:0      [点我收藏+]

标签:leetcode   divide two integers   

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的范围为[-21474836482147483647],正负两边的最大绝对值是不一样的。最简单的方法是用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) {
		// The first loop computes i.
		int i = 0;
		while (dividend >= divisor << 1) {
			divisor <<= 1;
			i++;
		}

		// The second loop computes the sum of non-zero coefficients.
		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; // Exact match.
			} else if (product < dividend) {
				ret = mid; // Cache this result.
				low = mid + 1;
			} else { // product > dividend.
				high = mid - 1;
			}
		}

		return (int) ret;
	}

[LeetCode] Divide Two Integers

标签:leetcode   divide two integers   

原文地址:http://blog.csdn.net/whuwangyi/article/details/40995863

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!