LeetCode 刷题记录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.
解法1:
由于不能进行乘法、除法和取余操作,所以只能用减法 计算减去的次数
此外我们要对非正数的除法操作转换为正数进行操作
直接对int值进行abs操作会出现问题,因为int型数字最小值是 231,在int范围内没有对应的正数,所以abs函数对于它的处理是不改变其值,所以我们要将int型转化为long long 型,然后进行操作
对于符号的处理可以采用被除数和除数的符号相乘来处理 int sign = (a / abs(a)) * (b / abs(b));
在c++中由于对abs做了重载所以abs可以处理long long的数而在c中不行,需用labs或llabs
坑:abs
还要考虑溢出处理 只有被除数是−231,除数为-1,结果是231,int 无法表示 ,应返回 231 − 1
还要考虑被除数的绝对值小于除数的绝对值,直接返回0,不用计算
最后还要考虑加速处理,如果直接暴力减会超时,每次将除数翻倍从而加速
例如:
m = 100 n = 3
100>=3 t=3 p=1
100>=(3<<1)=6 t翻倍为6 p翻倍为2
100>=(6<<1)=12 t翻倍为12 p翻倍为4
100>=(12<<1)=24 t翻倍为24 p翻倍为8
100>=(24<<1)=48 t翻倍为48 p翻倍为16
100>=(48<<1)=96 t翻倍为96 p翻倍为32
100 < (96<<1) 结束循环
res = 32
m = 4
4 >= 3 t=3 p=1
100<(3<<1)=6 结束循环
res = 33
m = 1
1<3 结束外层循环 得到结果33

while(m >= n){
            long long t = n, p = 1;
            while(m >= (t << 1)){
                t <<= 1;
                p <<= 1;
            }
            res += p;
            m -= t;
        }

c++:

class Solution {
public:
    int divide(int dividend, int divisor) {
        if(dividend == INT_MIN && divisor == -1) return INT_MAX;
        long long a = (long long)dividend;
        long long b = (long long)divisor;
        long long m = abs(a);
        long long n = abs(b);
        if(m < n) return 0;
        
        int sign = (a / abs(a)) *  (b / abs(b));
        long long res = 0;
        while(m >= n){
            long long t = n, p = 1;
            while(m >= (t << 1)){
                t <<= 1;
                p <<= 1;
            }
            res += p;
            m -= t;
        }
        return sign * res;
    }
};

java :
与c++相比没有long long 只有long 且 c++ long到int 可以自动转换,而java不行,会损失精度,需要强制类型转换(int)(sign * res)

class Solution {
    public int divide(int dividend, int divisor) {
       if(dividend == Integer.MIN_VALUE && divisor == -1) return Integer.MAX_VALUE;
        
        long a = (long)dividend;
        long b = (long)divisor;
        long m = Math.abs(a);
        long n = Math.abs(b);
        if(m < n) return 0;
        
        long sign = (a / Math.abs(a)) *  (b / Math.abs(b));
        long res = 0;
        while(m >= n){
            long t = n, p = 1;
            while(m >= (t << 1)){
                t <<= 1;
                p <<= 1;
            }
            res += p;
            m -= t;
        }
        return (int)(sign * res);
    }
}

Python:

注意左移操作 (2 << 30) - 1 表示的数为231-1
在这里插入图片描述
此外在Python3 中 / 为浮点数除而//为整数除
在这里插入图片描述

class Solution(object):
    def divide(self, dividend, divisor):
        """
        :type dividend: int
        :type divisor: int
        :rtype: int
        
        """
        if dividend == - (2 << 30) and divisor == -1: return (2 << 30) - 1
        m , n = abs(dividend) , abs(divisor)
        
        if m < n:return 0
        # sign = (dividend // m) *  (divisor // n)
        sign = (dividend / m) *  (divisor / n)
        res = 0
        while m >= n:
            t = n
            p = 1
            while m >= (t << 1):
                t <<= 1
                p <<= 1
            
            res += p
            m -= t
        
        return  sign * res

解法2:
与解法1相比
符号的表示也可以为if((dividend < 0) ^ (divisor < 0)) sign = -1;
异或操作 即两个数同为1 或者同为 0 结果为0 否则为1
也可以不在开头处理特殊情况,在最后检查是否溢出
c++:

class Solution {
public:
    int divide(int dividend, int divisor) {
        
        long long a = (long long)dividend;
        long long b = (long long)divisor;
        long long m = abs(a);
        long long n = abs(b);
        if(m < n) return 0;
        
        int sign = 1;
        if((dividend < 0) ^ (divisor < 0)) sign = -1;
        long long res = 0;
        while(m >= n){
            long long t = n, p = 1;
            while(m >= (t << 1)){
                t <<= 1;
                p <<= 1;
            }
            res += p;
            m -= t;
        }
        return sign * res > INT_MAX ? INT_MAX : sign * res;
    }
};

java:

class Solution {
    public int divide(int dividend, int divisor) {
       
        
        long a = (long)dividend;
        long b = (long)divisor;
        long m = Math.abs(a);
        long n = Math.abs(b);
        if(m < n) return 0;
        int sign = 1;
        if((dividend < 0) ^ (divisor < 0)) sign = -1;
        
        long res = 0;
        while(m >= n){
            long t = n, p = 1;
            while(m >= (t << 1)){
                t <<= 1;
                p <<= 1;
            }
            res += p;
            m -= t;
        }
        return (sign * res) > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int)(sign * res);
    }
}

python:

class Solution(object):
    def divide(self, dividend, divisor):
        """
        :type dividend: int
        :type divisor: int
        :rtype: int
        
        """
        m , n = abs(dividend) , abs(divisor)
        
        if m < n:return 0
        
        sign = 1
        if (dividend < 0) ^ (divisor < 0): sign = -1
        res = 0
        while m >= n:
            t = n
            p = 1
            while m >= (t << 1):
                t <<= 1
                p <<= 1
            
            res += p
            m -= t
        
        return ((2 << 30) - 1 ) if (sign * res) > ((2 << 30) - 1 ) else (sign * res)
      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值