算法题:整数除法

一.题目描述以及来源

给定两个整数 a 和 b ,求它们的除法的商 a/b ,要求不得使用乘号 '*'、除号 '/' 以及求余符号 '%' 。

注意:

整数除法的结果应当截去(truncate)其小数部分,例如:truncate(8.345) = 8 以及 truncate(-2.7335) = -2
假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231, 231−1]。本题中,如果除法结果溢出,则返回 231 − 1

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/xoh6Oh
 

例子:

输入:a = 15, b = 2
输出:7
解释:15/2 = truncate(7.5) = 7
输入:a = 7, b = -3
输出:-2
解释:7/-3 = truncate(-2.33333..) = -2
输入:a = 0, b = 1
输出:0
输入:a = 1, b = 1
输出:1

二.解题思路

a=15b=2k=0
15>=b(a>=b)a=13k=1
15-2>=bk=2
13-2>=b3
11-2>=b4
9-2>=b5
7-2>=b6
5-2>=b7
3-2<bend

因为不能用除法,所以只能使用减法去实现除法。

实现的代码如下:

public static void Divide(int a, int b)
    {
        //int sign = 1;
        //if((a>0 && b<0)||(a<0 && b > 0))
        //{
        //    sign= -1;
        //}
        int sign = (a > 0) ^ (b > 0) ? -1 : 1;
        a=Math.Abs(a); b=Math.Abs(b);
        int res = 0;
        while(a>=b)
        {
            a=a-b;
            res++;
        }
        if(sign==-1)
        {
            res = -res;
        }
        System.Console.WriteLine(res);
    }

此外还需要考虑,除法的符号,以及边界问题

 //时间复杂度是O(n),
    public static int DivideRange(int a, int b)
    {
        //32位最大值: 2^31-1=2147483647
        //32为最小值:-2^31=—2147483648
        //—2147483648/(-1)=2147483648>—2147483647 越界
        if ((a == (-2147483648)) && (b == (-1))){
            return 2147483647;
        }             
        int sign = (a > 0) ^ (b > 0) ? -1 : 1;
        //Math.Abs(—2147483648)=—2147483648  所以我们将正数转成负数去计算
        if (a > 0)
        {
            a = -a;
        }
        if (b > 0)
        {
            b = -b;
        }
        int res = 0;
        //-7 /-2  =3 ,都是负数除法 转成 数学,循环是<=   例如 -7<=-2 ,继续循环
        while (a <= b)
        {
            a = a - b;
            res++;
        }
        if (sign == -1)
        {
            res = -res;
        }
        return res;
    }

上面为解体的完整代码,需要注意的有

1.范围时,注意范围的边界(最小值/-1  会越界,最小值取正数 会保持原值)

2.将所有数转成负数去进行计算,因为最大值可以取相反数,最小值相反数越界

3.原本数字都变成正数的时候,判断是a>=b,作为循环的条件。转成负数计算的时候,循环的条件是a<=b

4.在c#中Integer.MIN_VALUE为


int max = int.MaxValue;
int min = int.MinValue;

三. 解题思路(2)

此思路看不懂的话可以去看看leetcode讲解视频:简单易懂Java/C++ /Python/js/go - 整数除法(剑指) - 整数除法 - 力扣(LeetCode)

 

public static int DivideVersion2(int a, int b)
    {
        //32位最大值: 2^31-1=2147483647
        //32为最小值:-2^31=—2147483648
        //—2147483648/(-1)=2147483648>—2147483647 越界
        if ((a == (-2147483648)) && (b == (-1)))
        {
            return 2147483647;
        }
        int sign = (a > 0) ^ (b > 0) ? -1 : 1;
        //Math.Abs(—2147483648)=—2147483648  所以我们将正数转成负数去计算
        if (a > 0)
        {
            a = -a;
        }
        if (b > 0)
        {
            b = -b;
        }
        int res = 0;
       
        //  22/7
        while (a <= b)
        {
            int value = b;
            int k = 1;
            while (a < value + value)
            {
                k = k + k;
                value = value + value;
            }
            res += k;
            a = a - value;

        }
        if (sign == -1)
        {
            res = -res;
        }
        System.Console.WriteLine(res);
        return res;
    }

此方法会超时,而且会有越域的情况

四,解题思路(3)位运算

在三的解题思路之上,我们知道我们可以实行b*2去减去a一半的情况。将b*2转换成b<<2,b往左移一位。

 

public class Solution {
    public int Divide(int a, int b) {
          if ((a == int.MinValue) && (b == (-1)))
        {
            return int.MaxValue;
        }
        int res = 0;

        if (b == int.MinValue) {
        return a == b? 1 : 0;
    }
         // 被除数先减去一个除数
    if (a == int.MinValue) {
        a -= -Math.Abs(b);
        res += 1;
    }


        int sign = (a > 0) ^ (b > 0) ? -1 : 1;
        a = Math.Abs(a); b = Math.Abs(b);
        
        for(int i = 31; i >= 0; i--)
        {
            if ((a >> i) - b >= 0)
            {   
                if (res > int.MaxValue - (1 << i)) {
                    return int.MinValue;
                }            
                a=a-(b<<i);
                res = res + (1<<i);
            }
        }
        if (sign == -1)
        {
            res = -res;
        }
        return res;
    }
}

 上面for循环内实现了整个逻辑,需要注意的是i=0是表示-b本身,所以需要i>=0.

 以下是处理边界值的代码,测试之前没发现。


        if (b == int.MinValue) {
        return a == b? 1 : 0;
    }
         // 被除数先减去一个除数
    if (a == int.MinValue) {
        a -= -Math.Abs(b);
        res += 1;
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值