力扣2531-剑指offer II 001 : 整数除法

力扣2531-剑指offer II 001 : 整数除法

题目

给定两个整数 a 和 b ,求它们的除法的商 a/b ,要求不得使用乘号 ‘*’、除号 ‘/’ 以及求余符号 ‘%’ 。
注意:
整数除法的结果应当截去(truncate)其小数部分,例如:truncate(8.345) = 8 以及 truncate(-2.7335) = -2
假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−2^31, 2的31次方−1]。本题中,如果除法结果溢出,则返回 2的31次方 − 1

代码带注释

#include <iostream>
#include <limits.h>
using namespace std;

class Solution {
public:
    /* 将a和b都化成正整数,但-2147483648的绝对值还是-2147483648  因为在数字在计算机中存储都是以补码的形式 
     * 那么就不会满足循环条件,就立马退出
     * 如果换成负整数,则不会发生此问题
     *  空间复杂度o(1),时间复杂度o(n) 因为如果a=-2147483648 b=1; k = 2147483648 = n
    */
    int divide(int a, int b) 
    {
       int sign = (a > 0)^(b > 0) ? -1 : 1;
       // 一、考虑越界问题
       // 32位最大值:2^31-1 = 2147483647
       // 32位最小值:-2^31 = -2147483648
       // 如果a = -2147483648 b = -1 那么结果是 2147483648 越界
       if(a == INT_MIN && b == -1)
       {
          return INT_MAX;
       }
       //二、考虑题目要求
      //因为题目要求只支持32位
      //  a = abs(a);
      //  b = abs(b);
      if(a>0)a = -a;
      if(b>0)b = -b;
       int res = 0;
       while(a <= b)
       {
          a -= b;
          res++;
       }
       // 不能用乘号,所以将乘号换成三目运算符
       return sign == 1 ? res : -res;   
    }

    /* 
     *  空间复杂度o(1),时间复杂度:O(logn * logn),n 是最大值 2147483647 --> 10^10
    */
    int divide_1(int a, int b) 
    {
      if(a == INT_MIN && b == -1)
       {
          return INT_MAX;
       }
      int sign = (a > 0)^(b > 0) ? -1 : 1;
      if(a>0)a = -a;
      if(b>0)b = -b;
      cout<<"a:"<<a<<" b:"<<b<<endl;
       int res = 0;
       while(a <= b)
       {
          int value = b;  
          int k = 1;
        // 0xc0000000 是十进制 -2^30 的十六进制的表示
        // 判断 value >= 0xc0000000 的原因:保证 value + value 不会溢出
        // 可以这样判断的原因是:0xc0000000 是最小值 -2^31 的一半,
        // 而 a 的值不可能比 -2^31 还要小,所以 value 不可能比 0xc0000000 小
        // -2^31 / 2 = -2^30
          while(value >= 0xc0000000 && a <= value + value){
            value += value;
            //如果k = 最大值的一半的话,INT_MAX/2 = 1,073,741,823.5 那么直接返回最小值
            //因为这个时候k+k肯定会大于 2147483648 这个超过了题目给出的范围
            if(k>1073741823){
              return INT_MIN;
            }
            k += k; 
          }
          a -= value;
          res += k;
       }
        cout<<"rojek"<<endl;
       return sign == 1 ? res : -res;   
    }

};

int main()
{
    system("chcp 65001");
    Solution a1;
    int result = a1.divide_1(-2147483648,1);
    cout<<"result: "<<result<<endl;
    // cout<<pow(2,31)-1<<endl;
    return 0;
}

注意问题

1.由于题目限制了数字的使用范围,如果将负数全部化为整数处理 那么会出现
这样问题 对int的最小值-2^31取绝对值 会等于该数 ,因为在计算机中存储的数字都是以补码的形式来存储的限定了int32位范围 那么就会产生溢出,如果换成long的话 那么久不会符合题目的要求
2.整数的补码就是其本身,负数的补码等于反码+1
具体可以参考一下链接:
1.https://www.jianshu.com/p/5d899b71266d?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation
2.https://blog.csdn.net/qq_44715943/article/details/115418965?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-2-115418965-blog-7429197.pc_relevant_multi_platform_featuressortv2dupreplace&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-2-115418965-blog-7429197.pc_relevant_multi_platform_featuressortv2dupreplace&utm_relevant_index=5
3.在线程序计算器
http://cal.apple886.com/

做题步骤

1.先把基本(能实现大部分样例的)的代码写出来
2.再注意边界问题
3.再回过来仔细阅读题目的要求
做到不紧不慢,有条理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值