LeetCode 29. 两数相除模拟减法 + 位运算解决 两数相除

原题链接:https://leetcode-cn.com/problems/divide-two-integers/

解题思路

此题的思路就除法的基本过程进行模拟的一个方法:
在一个除法算式中,对于 被除数 ÷ 除数 = 商 ... 余数,所以,我们能很快的想到 商 * 除数 + 余数 = 被除数

  • 首先,对于本题,开始想到的方法就是将被除数减除数,看能够减多少次,那么最后的结果就是多少。但是,如果是Integer.MIN_VALUE 除以-1,则需要循环的次数过大,导致TLE.

可以考虑使用位移法来解决此题目。设被除数为x,除数为y。 假设n开始就是31,那么我们可以不断的去缩小n的值,并判断 (2 ^ n) * y是否是小于等于x的,如果满足小于的条件,将2^n累加到结果中,最后将x减去对应的(2 ^ n) * y。重复这个过程…

此方法的优化地方,就是在于利用位移的操作,将原来记录被除数能减多少个除数的过程进行了加速,及时不再是一个一个的减,而是从2^31 * 除数,2^30 * 除数 …开始减,而判断能否减去对应的 2^n * 除数,就是利用当前 被除数 是否大于 2 ^ 31 * 除数。

例子:33/1为例子:

没有优化的方法 : 33 - 1要减 33次,所以最后结果输出33.

优化之后的方法: 33 开始尝试减去 2^31 * 1不行,依次类推2^31,..., 2^5 * 1满足小于的情况,所以, 33 >= 2^5 * 1。将2^5累加到结果中,后继续运算,33 - 2 ^ 5 * 1 = 1, 被除数变成了1, 继续从2^4开始,一直到1 >= 2 ^ 0 * 1,将2^0累加到结果中,结束运算,所以,最后的结果是2^5 + 2^0 = 33
代码实现如下!

代码
JAVA代码

class Solution {
    public int divide(int x, int y) {
        // 如果是等于零的话,没有意义
       if(y == 0) return 0;
       // 判断当前可能会溢出的情况只有这个一种
       if(x == Integer.MIN_VALUE && y == -1) return Integer.MAX_VALUE;
       // 记录当前的正负性
       boolean negative = (x ^ y) < 0;
       // 由于a可能需要处理移除的问题,用long类型进行存储
       long a = Math.abs((long)x);
       long b = Math.abs((long)y);
       int res = 0;
       for(int i = 31; i >=0; i--){
           // 每次判断当前是否达到除数的标准
           if(a >> i >= b){
               res += 1 << i;
               // 减去相应的值
               a -= b << i;
           }
       }
       return negative ? -res:res;

    }
}

C++ 代码

class Solution {
public:
    int divide(int x, int y) {
        typedef long long LL;
        //将所有的值都添加到一个集合中 
        vector<LL> exp;
        bool is_minus = false;
        if(x < 0 && y > 0 || x > 0 && y < 0) is_minus = true;
        // 将所得的二进制乘法放到集合中 
        LL a = abs((LL)x), b = abs((LL)y);
        for(LL i = b; i <= a; i = i + i) exp.push_back(i);
        LL res = 0;
        for(int i = exp.size() - 1; i >= 0; i--)
        {
            if(a >= exp[i])
            {
                a-=exp[i];
                res += 1ll << i;
            }
        }
        if( is_minus) res = -res;
        if(res > INT_MAX || res < INT_MIN) res = INT_MAX;
        return res;
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值