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;
    }
};
原文地址:https://www.cnblogs.com/yaoyudadudu/p/9148620.html