• 剑指offer1整数除法


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

    注意:

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

    示例 1:

    输入:a = 15, b = 2
    输出:7
    解释:15/2 = truncate(7.5) = 7
    示例 2:

    输入:a = 7, b = -3
    输出:-2
    解释:7/-3 = truncate(-2.33333..) = -2
    示例 3:

    输入:a = 0, b = 1
    输出:0
    示例 4:

    输入:a = 1, b = 1
    输出:1
     

    提示:

    -231 <= a, b <= 231 - 1
    b != 0

    链接:https://leetcode-cn.com/problems/xoh6Oh
    题解:最简单的方法,记录a中有几个b。

    问题一、边界数据

    INT_MIN int 类型的变量的最小值。 -2147483648
    INT_MAX int 类型的变量的最大值。 2147483647

    如果是INT_MIN 除 -1答案会是2147483648,超过了int最大值   这里要特判一下:

    if (a == INT_MIN && b == 1) return INT_MIN;
    if (a == INT_MIN && b ==-1) return INT_MAX;

    同时对于计数值unsigned int  ,如果不用:那么当 a = -2147483648, b = 1 的时候,k 会越界

    问题二、时间超限

    while(x>=y)
    {
    x-=y,c++;
    } 这样的时间复杂度的O(n)实测会超时。借助类似倍数,减少循环次数,k的最大值是log(n),这样计算次数就变成log(n)*log(n)了

     1  while (a <= b) {
     2         int value = b;
     3         unsigned int k = 1;
     4         while (value >= 0xc0000000 && a <= value + value) {//确保不越界
     5             k += k;
     6             value += value;
     7         }
     8         a -= value;
     9         res += k;
    10     }

    完整代码

    class Solution {
    public:
        int divide(int a, int b) {
             unsigned int  c=0;
             int res=1;
             if (a == INT_MIN && b == 1) return INT_MIN;
             if (a == INT_MIN && b ==-1) return INT_MAX;
             if((a<0&&b>0)||(a>0&&b<0)) res=-1;
             if(a>0) a=-a;
             if(b>0) b=-b;
             while(a<=b)
             {
                unsigned int  k=1,va=b;
                while(a<0xc0000000&&a<=va+va)
                {
                    va+=va,k+=k;
                }
               //printf("%d %d %d %d\n",a,b,k,c);
                a-=va;
                c+=k;
            }
            if(res==1) return c;
            else return -c;
        }
    };
    View Code

    还可以用位运算优化,变成O(1)复杂度

    int divide(int a, int b) {
        if (a == INT_MIN && b == -1) return INT_MAX;
    
        int sign = (a > 0) ^ (b > 0) ? -1 : 1;
    
        unsigned int ua = abs(a);
        unsigned int ub = abs(b);
        unsigned int res = 0;
        for (int i = 31; i >= 0; i--) {
            if ((ua >> i) >= ub) {
                ua = ua - (ub << i);
                res += 1 << i;
            }
        }
        // bug 修复:因为不能使用乘号,所以将乘号换成三目运算符
        return sign == 1 ? res : -res;
    }
    View Code
  • 相关阅读:
    LeetCode 560. Subarray Sum Equals K (子数组之和等于K)
    25、LinkedList特有方法
    24、List三个子类的特点
    23、数据结构之数组和链表
    22、Vector简介
    21、List遍历时修改元素的问题
    20、List集合中特有的方法
    19、集合概述
    18、Random类简介
    17、enum简介
  • 原文地址:https://www.cnblogs.com/sylvia1111/p/15712433.html
Copyright © 2020-2023  润新知