LeetCode算法系列:29. Divide Two Integers

版权声明:由于一些问题,理论类博客放到了blogger上,希望各位看官莅临指教https://efanbh.blogspot.com/;本文为博主原创文章,转载请注明本文来源 https://blog.csdn.net/wyf826459/article/details/82014970

目录

 

题目描述:

算法实现

一、纯减法

二、官网方法

三、个人在官网方法启发下写的算法

attention:


题目描述:
 

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.

算法实现

首先为了方便,将题目改造成,正整数除以正整数,这个过程不在叙述


一、纯减法

最简单的方法就是写一个循环,用被除数不断的减去减数,直到被减数小于减数,但是会超时


二、官网方法

具体思路为,我减去的不再是减数,而是减去减数的倍数,可是又不能使用乘法,那么减数的倍数怎么实现呢?用移位的方式;

//官网实际答案
class Solution {
public:
    int divide(int dividend, int divisor) {
        long long a = abs((double)dividend);
        long long b = abs((double)divisor);
        
        long long ret = 0;
        while (a >= b) {
            long long c = b;
            for (int i = 0; a >= c; ++i, c <<= 1) {
                //std::cout<<"1-1 a="<<a<<", c="<<c<<" ,i="<<i<<" ,ret="<<ret<<std::endl;
                a -= c;
                ret += 1 << i;
                //std::cout<<"1-2 a="<<a<<", c="<<c<<" ,i="<<i<<" ,ret="<<ret<<std::endl;
            }
        }
        return ((dividend^divisor)>>31) ? (int)(-ret) : (int)(ret);
    }

看两个例子

//49/7
1-1 a=49, c=7 ,i=0 ,ret=0
1-2 a=42, c=7 ,i=0 ,ret=1
1-1 a=42, c=14 ,i=1 ,ret=1
1-2 a=28, c=14 ,i=1 ,ret=3
1-1 a=28, c=28 ,i=2 ,ret=3
1-2 a=0, c=28 ,i=2 ,ret=7
49 / 7 = 7
// 64/7
1-1 a=64, c=7 ,i=0 ,ret=0
1-2 a=57, c=7 ,i=0 ,ret=1
1-1 a=57, c=14 ,i=1 ,ret=1
1-2 a=43, c=14 ,i=1 ,ret=3
1-1 a=43, c=28 ,i=2 ,ret=3
1-2 a=15, c=28 ,i=2 ,ret=7
1-1 a=15, c=7 ,i=0 ,ret=7
1-2 a=8, c=7 ,i=0 ,ret=8
1-1 a=8, c=7 ,i=0 ,ret=8
1-2 a=1, c=7 ,i=0 ,ret=9
64 / 7 = 9

三、个人在官网方法启发下写的算法

与前一种方法不同,我所寻找的是能够小于被减数的,减数能够左移的最大位数,使被减数减去这一移位完成的数值,不断重复,直到减数小于被减数。具体采用递归的方式实现

class Solution {
public:
    long long divide_plus(long long a, long long b){
        if(a < b) return 0;
        long long i = 1;
        long long c = b;
        while(c <= a) 
        {
            c = c << 1;
            i = i << 1;
        }
        return (i >> 1) + divide_plus(a - (c >> 1), b);
    }
    int divide(int dividend, int divisor) {
        bool flag;
        if(dividend == 0) return 0;
        if((dividend > 0 && divisor > 0) || (dividend < 0 && divisor < 0))flag = true;
        if((dividend > 0 && divisor < 0) || (dividend < 0 && divisor > 0))flag = false;
        long long a = abs((long long)(dividend));
        long long b = abs((long long)(divisor));
        long long res = flag==true ? divide_plus(a,b) : -divide_plus(a,b);
        if(res > INT_MAX) return INT_MAX;
        if(res < INT_MIN) return INT_MIN; 
        return int(res);
    }
};

attention:

  1. 无论是官网解法abs((double)dividend)中的强制转换为double型,还是我自己实现的算法中转化成long long型都是防止INT_MIN的绝对值溢出
  2. 不知道为什么不管是数值超出INT_MAX还是数值小于INT_MIN,强制转换为int后的结果都是INT_MIN。因此是通过判断大小来将其数值范围限定在INT范围内的,而不是通过强制转换来实现。

猜你喜欢

转载自blog.csdn.net/wyf826459/article/details/82014970