力扣每日一题29:两数相除

题目描述:

给你两个整数,被除数 dividend 和除数 divisor。将两数相除,要求 不使用 乘法、除法和取余运算。

整数除法应该向零截断,也就是截去(truncate)其小数部分。例如,8.345 将被截断为 8 ,-2.7335 将被截断至 -2 。

返回被除数 dividend 除以除数 divisor 得到的  。

注意:假设我们的环境只能存储 32 位 有符号整数,其数值范围是 [−231,  231 − 1] 。本题中,如果商 严格大于 231 − 1 ,则返回 231 − 1 ;如果商 严格小于 -231 ,则返回 -231 。

示例 1:

输入: dividend = 10, divisor = 3
输出: 3
解释: 10/3 = 3.33333.. ,向零截断后得到 3 。

示例 2:

输入: dividend = 7, divisor = -3
输出: -2
解释: 7/-3 = -2.33333.. ,向零截断后得到 -2 。

提示:

  • -231 <= dividend, divisor <= 231 - 1
  • divisor != 0

通过次数

220.1K

提交次数

989.4K

通过率

22.2%

题目分析:

本题看似很简单,却有三个难点或者说是易错点。

一、不能使用乘法,除法,取余运算。

所以我们只能用减法运算或者是位运算来代替除法运算。

二、题目环境下只能存储32位有符号整数。

也就是说你写的代码里出现的数的范围只能在[-2^32,2^31-1]里。但是(-2^31)/(-1)=2^31超出了这个范围,所以要单独拿出来讨论。

三、排除掉被除数x和除数y为0的情况,x、y的正负性有四种情况。

当x,y同号时,x能减多少个y并且不变号(变为0算作变号),x/y就等于多少。

当x、y异号时,x能加多少个y并且不变号(变为0算作变号),-x/y就等于多少。

为了方便计算,我们可以用一个属sign先记住x,y同号还是异号,然后再将x,y变为同号,用cnt记录x-y且x不变号的次数,同号的话x/y就等于cnt,异号的话x/y就等于-cnt。

所以x,y都变为正号还是都变为负号呢?考虑到-2^31变号后会超出int类型,我们还是变为正号比较好。当x,y都变为负号后,对于y==-1这种情况,如果直接减的话,会减很多次,最终会超时。所以我们可以在不超出int类型的情况下,先扩大步长,比如说先一次性减十个y,当减不到10y的时候,再减y。

代码:

int divide(int dividend, int divisor)
{
    int max=pow(2,31)-1;
    int min=-pow(2,31);
    int x=dividend,y=divisor;
    //对于几种特殊情况
    if(x==min)
    {
        if(y==1) return min;
        else if(y==-1) return max;
    }
    if(y==min)
    {
        if(x==min) return 1;
        else return 0;
    }
    if(x==0)
    {
        return 0;
    }
    //把x,y都变成负的来算
    int sign;
    if( (x>0&&y>0)||(x<0&&y<0) ) sign=1;
    else sign=-1;
    int cnt=0;
    x=x>0?-x:x;
    y=y>0?-y:y;
    //扩大步长(步长不能超过int范围)
    if(y>-1000)
    {
        int step=y+y+y+y+y+y+y+y+y+y;
        while(x<=step)
        {
            x-=step;
            cnt+=10;
        }
    }
    while(x<=y)
    {
        x-=y;
        cnt++;
    }
    cnt=(sign==1)?cnt:-cnt;
    return cnt;
}

你可能感兴趣的:(LeetCode每日一题,leetcode,算法,职场和发展)