1. 题目

在这里插入图片描述
在这里插入图片描述

2. 读题(需要重点注意的东西)

思路(二进制优化):
主要思路是用减法减出最后所需要的商,但是一个个减是肯定会超时的,那么怎么优化呢?


二进制优化:
可以考虑使用二进制的方式来减,这就将所需减次数从n次缩小到了logn次:
设被除数为x,除数为y,则可以预处理出2^30^y、2^29^y、2^28^y、...、2^0^y的值,然后从大到小去看每一项,即如果被除数x大于230y,则使得x = x - 230y,依次类推 229y、228y、…、20y,即可反推出商。


接下来给个例子辅助理解:
设有被除数为十进制数50,除数为9,预处理出22 * 9 = 36 , 21 * 9 = 18, 20 * 9 = 9
则有:
50 - 22 * 9 = 50 - 36 = 14
14 - 20 * 9 = 5
得到余数为5,商为22 + 20 = 5


代码实现步骤:

  1. 处理符号,如果x和y的符号不同,需要全部处理为正数,若符号不同,最后则需要在答案中加上一个负号。(注意,最小负数的绝对值比最大正数多1,因此最小的负数转为正数后可能会溢出,因此要用longlong来存储转换后的值
  2. 计算 230y、229y、228y、…、20y的值
  3. 特判,若答案溢出,则返回 Integer.MAX_VALUE

3. 解法

---------------------------------------------------解法---------------------------------------------------

class Solution {
    public int divide(int x, int y) {
    	// 特判
        if(x == -2147483648 && y == 1) return Integer.MIN_VALUE;
        // 处理符号
        int flag = 1;
        if(x > 0 && y < 0 || x < 0 && y > 0) flag = -1;
        long a = x,b = y;
        if(a < 0) a = -a;
        if(b < 0) b = -b;
        // 预处理出2的各个次方乘y的结果
        long[] exp = new long[31];
        for(int i = 0;i < 31;i++) exp[i] = (1 << i) * b;
        
        // 减出商
        long res = 0;
        for(int i = 30;i >= 0;i--){
            if(a - exp[i] >= 0){
                a -= exp[i];
                res += (long)1 << i;
            }
        }
        res = flag*res;
        if(res > Integer.MAX_VALUE || res < Integer.MIN_VALUE) return Integer.MAX_VALUE;
        return (int)res;
    }
}

4. 可能有帮助的前置习题

5. 所用到的数据结构与算法思想

  • 二进制优化

6. 总结

用二进制优化来使得时间复杂度优化为logn级,注意边界条件

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐