[ LeetCode ]#29. Divide Two Integers(两数相除 C++ & Python)

本文介绍了一种不使用乘法、除法和取余运算实现两整数相除的方法,通过位移运算提高效率,避免了传统辗转相减法在大数情况下的效率低下问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目: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: [−2^31,  2^31 − 1]. For the purpose of this problem, assume that your function returns 2^31 − 1 when the division result overflows.

题意:

给两个整数,求两个数相除的余数,要求不使用乘法、除法、取余运算。

note:除数与被除数均为32位有符号整数;保证除数不为0;并且假设编译环境使用32位所能存储的数值范围为[-2^31, 2^31-1],如若结果发生溢出则返回2^31-1。

分析:

一种比较直接的思路可以使用辗转相减法,直到dividend<divisor.即可返回相减的次数。

如果除数很小,而被除数很大,辗转相减法必然效率极其低下,事实证明边界值均在测试样例中。见Code1.

所以另一种思路可以首先判断出被除数与除数之间的倍数关系,但是由于题目要求不可以使用乘除法,因此这里可以使用位移运算代替,然后再在小范围内求出精确结果。见Code2

以上两种得到的结果最后均需要判断是否发成了溢出。

Code1

class Solution {
public:
    int divide(int dividend, int divisor) {
        int flag=1;
        long long a = dividend, b = divisor;
        if(a<0){
            a=-a;
            flag*=-1;
        }else if(a==0){
            return 0;
        }
        if(b<0){
            b=-b;
            flag*=-1;
        }else if(b==1){
            return dividend;
        }
        if(a==b)
            return flag;
        if(b==1){
            return a-1;
        }
        int sum=0;    // 以上均为处理边界特殊情况
        while(a>=b){    
            a-=b;
            ++sum;
        }
        return sum*flag;
    }
};

结果:

Runtime: 2020 ms, faster than 27.56% of C++ online submissions for Divide Two Integers.

Memory Usage: 13.7 MB, less than 68.85% of C++ online submissions for Divide Two Integers.

Code2:

class Solution {
public:
    int divide(int a, int b) {
        long long signal = (a<0 ^ b<0)?-1:1;    // 使用异或运算判断a,b是否异号
        int shift = 0;    // 用于记录位移量
        long long dividend = a>0?a:-(long long)a;    
        long long divisor = b>0?b:-(long long)b;
        while(dividend<<shift >= divisor)++shift;    
        int bits = shift-1;    //bits 记录dividend大于divisor的最大倍数,这里用位移表示。
        long long ans=0;
        while(bits>=0){
            if(dividend >= divisor<<bits){    // 依次减小位移量,精确最终的结果
                dividend -= divisor<<bits;
                ans += 1LL<<bits;
            }
            --bits;
        }
        ans *= signal;
        if(ans<numeric_limits<int>::min() || ans>numeric_limits<int>::max()){    //判断溢出
            return numeric_limits<int>::max();
        }
        return ans;
    }
};

结果:

Runtime: 12 ms, faster than 99.63% of C++ online submissions for Divide Two Integers.

Memory Usage: 13.8 MB, less than 29.59% of C++ online submissions for Divide Two Integers.

可见使用位移操作可以使程序的运行速度提升两个量级。

Code2 & Python

class Solution:
    def divide(self, dividend: int, divisor: int) -> int:
        sift , signal = 0 , 1
        if dividend < 0:
            signal *= -1
            dividend = -dividend
        if divisor < 0:
            signal *= -1
            divisor = -divisor
        while dividend>>sift >= divisor:sift+=1
        bits = sift-1
        ans=0

        while bits>=0:
            if dividend >= divisor<<bits:
                dividend -= divisor<<bits
                ans += 1<<bits
            bits-=1

        INT_MIN, INT_MAX = -(1<<31), (1<<31)-1
        ans *= signal
        if ans<INT_MIN or ans>INT_MAX:
            return INT_MAX
        return ans

结果:

Runtime: 56 ms, faster than 58.53% of Python3 online submissions for Divide Two Integers.

Memory Usage: 13.3 MB, less than 5.26% of Python3 online submissions for Divide Two Integers.

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值