• 算法题:整数除法


    一.题目描述以及来源

    给定两个整数 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
     

    例子:

    1. 输入:a = 15, b = 2
    2. 输出:7
    3. 解释:15/2 = truncate(7.5) = 7
    1. 输入:a = 7, b = -3
    2. 输出:-2
    3. 解释:7/-3 = truncate(-2.33333..) = -2
    1. 输入:a = 0, b = 1
    2. 输出:0
    1. 输入:a = 1, b = 1
    2. 输出: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-2end

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

    实现的代码如下:

    1. public static void Divide(int a, int b)
    2. {
    3. //int sign = 1;
    4. //if((a>0 && b<0)||(a<0 && b > 0))
    5. //{
    6. // sign= -1;
    7. //}
    8. int sign = (a > 0) ^ (b > 0) ? -1 : 1;
    9. a=Math.Abs(a); b=Math.Abs(b);
    10. int res = 0;
    11. while(a>=b)
    12. {
    13. a=a-b;
    14. res++;
    15. }
    16. if(sign==-1)
    17. {
    18. res = -res;
    19. }
    20. System.Console.WriteLine(res);
    21. }

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

    1. //时间复杂度是O(n),
    2. public static int DivideRange(int a, int b)
    3. {
    4. //32位最大值: 2^31-1=2147483647
    5. //32为最小值:-2^31=—2147483648
    6. //—2147483648/(-1)=2147483648>—2147483647 越界
    7. if ((a == (-2147483648)) && (b == (-1))){
    8. return 2147483647;
    9. }
    10. int sign = (a > 0) ^ (b > 0) ? -1 : 1;
    11. //Math.Abs(—2147483648)=—2147483648 所以我们将正数转成负数去计算
    12. if (a > 0)
    13. {
    14. a = -a;
    15. }
    16. if (b > 0)
    17. {
    18. b = -b;
    19. }
    20. int res = 0;
    21. //-7 /-2 =3 ,都是负数除法 转成 数学,循环是<= 例如 -7<=-2 ,继续循环
    22. while (a <= b)
    23. {
    24. a = a - b;
    25. res++;
    26. }
    27. if (sign == -1)
    28. {
    29. res = -res;
    30. }
    31. return res;
    32. }

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

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

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

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

    4.在c#中Integer.MIN_VALUE为

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

    三. 解题思路(2)

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

     

    1. public static int DivideVersion2(int a, int b)
    2. {
    3. //32位最大值: 2^31-1=2147483647
    4. //32为最小值:-2^31=—2147483648
    5. //—2147483648/(-1)=2147483648>—2147483647 越界
    6. if ((a == (-2147483648)) && (b == (-1)))
    7. {
    8. return 2147483647;
    9. }
    10. int sign = (a > 0) ^ (b > 0) ? -1 : 1;
    11. //Math.Abs(—2147483648)=—2147483648 所以我们将正数转成负数去计算
    12. if (a > 0)
    13. {
    14. a = -a;
    15. }
    16. if (b > 0)
    17. {
    18. b = -b;
    19. }
    20. int res = 0;
    21. // 22/7
    22. while (a <= b)
    23. {
    24. int value = b;
    25. int k = 1;
    26. while (a < value + value)
    27. {
    28. k = k + k;
    29. value = value + value;
    30. }
    31. res += k;
    32. a = a - value;
    33. }
    34. if (sign == -1)
    35. {
    36. res = -res;
    37. }
    38. System.Console.WriteLine(res);
    39. return res;
    40. }

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

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

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

     

    1. public class Solution {
    2. public int Divide(int a, int b) {
    3. if ((a == int.MinValue) && (b == (-1)))
    4. {
    5. return int.MaxValue;
    6. }
    7. int res = 0;
    8. if (b == int.MinValue) {
    9. return a == b? 1 : 0;
    10. }
    11. // 被除数先减去一个除数
    12. if (a == int.MinValue) {
    13. a -= -Math.Abs(b);
    14. res += 1;
    15. }
    16. int sign = (a > 0) ^ (b > 0) ? -1 : 1;
    17. a = Math.Abs(a); b = Math.Abs(b);
    18. for(int i = 31; i >= 0; i--)
    19. {
    20. if ((a >> i) - b >= 0)
    21. {
    22. if (res > int.MaxValue - (1 << i)) {
    23. return int.MinValue;
    24. }
    25. a=a-(b<
    26. res = res + (1<
    27. }
    28. }
    29. if (sign == -1)
    30. {
    31. res = -res;
    32. }
    33. return res;
    34. }
    35. }

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

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

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

  • 相关阅读:
    开源医疗大模型排行榜: 健康领域大模型基准测试
    java智慧校园信息管理系统源码带微信小程序
    为什么在使用onnxruntime-gpu下却没有成功调用GPU?
    计算机毕业设计Java知识管理系统(源码+系统+mysql数据库+Lw文档)
    设计模式 - 命令模式
    【面经】特斯拉大数据开发笔经
    通用的方法在任何云VM上安装Mikrotik的Cloud Hosted Router
    三种常见的移动底盘运动学模型分析
    二进制部署kubernetes集群的推荐方式
    C语言学习之路(基础篇)—— 数据类型 02
  • 原文地址:https://blog.csdn.net/hellolianhua/article/details/128100072