29. Divide Two Integers
问题描述:
Given two integers dividend
and divisor
, divide two integers without using multiplication, division and mod operator.
Return the quotient after dividing dividend
by divisor
.
The integer division should truncate toward zero.
Example 1:
Input: dividend = 10, divisor = 3 Output: 3
Example 2:
Input: dividend = 7, divisor = -3 Output: -2
Note:
- Both dividend and divisor will be 32-bit signed integers.
- The divisor will never be 0.
- Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [−231, 231 − 1]. For the purpose of this problem, assume that your function returns 231 − 1 when the division result overflows.
解题思路:
这道题要起计算两个数的商,看起来很简单,但是题目要求了:不能用乘*,不能用除/,不能用模%。
emmmmm……那不就是只能用加和减了?
一开始我用了减,根据定义来,oj倒是过了,但是1000+ms啊我的朋友们,直方图上都见不到我(我觉得可以用二分查找进行优化)。
痛定思痛后看了别人的代码。
大神们用位操作做的。。
主要是用的左移操作:<<。 左移操作一次相当于*2
我们可以将除数左移并将其与被除数比较大小, 当除数左移至大于被除数时,停止左移,获得当前的差值(dividend - divosor)把差值作为新的被除数,用原来的除数左移并于新的被除数比较大小。
举一个具体的例子
25 / 4
4 << 1 -->8 < 25
8 << 1 -->16 < 25
16 << 1 --> 32 > 25 break
新的被除数为:25 - 16 = 7
4 << 1 ---> 8 > 7
彻底退出。
在这里我们用两个while循环来实现
外层循环比较除数与被除数大小,只要进了外层循环,说明除数小于被除数。那么结果至少要为1.
内层循环判断为商2的多少倍:
因为我们每次对除数进行左移1位,实际上是乘2,所以商也要左移1位,即乘二。
代码:
class Solution { public: int divide(int dividend, int divisor) { if(divisor == 0 || (divisor == -1 && dividend == INT_MIN)) return INT_MAX; int sign = ((dividend < 0) ^ (divisor < 0)) ? -1 : 1; long m = abs((long)dividend ); long n = abs((long)divisor); if(m < n) return 0; long ret = 0; if(n == 1) return sign == 1 ? m : -m; while(n <= m){ long t = n; long p = 1; while(m >= (t<<1)){ p <<=1; t <<=1; } ret += p; m -= t; } return sign == 1 ? ret : -ret; } };