剑指offer专项突破版

面试题1:整除除法

力扣连接:https://leetcode-cn.com/problems/xoh6Oh/submissions/

题目描述

输入两个int型整数,它们进行除法计算并返回商,要求不得使用乘号‘*’、除号’/‘及求余符号’%’。当发生溢出时,返回最大的整数值。
其中b!=0,-231 <=a,b<= 231-1;

样例输入1

a=15 ,b=2

样例输出1

7

样例输入2

a=7 ,b= -3

样例输出2

-2

样例输入3

a=0 ,b=1

样例输出3

0


暴力循环O(n)

这个题目限制我们不能使用乘号、除号进行运算。一个直观的解法就是基于减法实现除法。
例如,为了求得15/2的商,可以不断地从15里减去2,当减去7个2之后余数是1,此时不能再减去更多的2,因此15/2的商是7。可以用循环实现这一过程。在实现之前,先考虑数据溢出的问题:

  1. 对于int类型来说,能表示的数据范围在[-231,231-1]之间,只有当a=-231,b=-1的时候a/b的结果超过int所能表示的最大整数范围造成数据溢出,此时直接返回INT_MAX即可。
  2. 对于除数或者被除数是负数的情况,考虑到负数-231变成正数会造成数据溢出,所以把被除数和除数都变成负数,再进行运算。
class Solution {
public:
    int divide(int a, int b) {
        if(a==INT_MIN && b==-1) return INT_MAX;
        int ans=0;
        int flag=2;
        if(a>0) {a=-a;flag--;}
        if(b>0) {b=-b;flag--;}
        while(a<=b){
            ans++;
            a-=b;
        }
        if(flag==1) ans=-ans;
        return ans;
    }
};

这个程序的时间复杂度是O(n),当a非常大而b又非常小的时候,会超出时间限制,所以要做出优化。


优化O(logn)

在暴力循环的基础上进行优化。(此时被除数和除数都是负数)
当被除数小于等于除数时,继续比较判断被除数是否小于等于除数的2倍,如果是,则继续判断被除数是否小于等于除数的4倍、8倍…等。如果被除数a最多小于等于除数的2k倍,那么被除数减去除数的2k倍,这部分的商是2k,然后将被除数重复前面的步骤直到被除数a大于b。

举例

a=15,b=3
res=0记录最后结果
全部变为负数
a=-15,b=-3

第一次循环

pin=1记录本部分的商
value=b记录除数
-15 < -3-3 ----------->value=-6 ;pin=2
-15 < -6-6 ----------->value=-12;pin=4
-15 > -12-12---------->res=4;a=-3

第二次循环

pin=1
value=b
-3 > -3-3---------->res=5;a=0

第三次循环

a>b----------> 退出循环
因为原本两个数都是正数所以返回5;

class Solution {
public:
    int divide(int a, int b) {
        if(a==INT_MIN && b==-1) return INT_MAX;
        if(b==1) return a;
        int ans=0;
        int flag=2;
        if(a>0) {a=-a;flag--;}
        if(b>0) {b=-b;flag--;}
        while(a<=b){
            int value=b;//除数
            int pin=1;//商
            while(value>=INT_MIN/2 && a<=value+value){
                /*为了防止value+value之后产生数据溢出,
                应该让value>=INT_MIN的一半。
                之所以是大于等于是因为value是一个负数*/
                pin+=pin;
                value+=value;
            }
            ans+=pin;
            a-=value;
        }
        if(flag==1) ans=-ans;
        return ans;
    }
};

在这里插入图片描述

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值