LeetCode算法系列:29. Divide Two Integers

目录

 

题目描述:

算法实现

一、纯减法

二、官网方法

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

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范围内的,而不是通过强制转换来实现。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值