码迷,mamicode.com
首页 > 其他好文 > 详细

LeetCode 29 - 两数相除 - [位运算]

时间:2018-11-08 13:17:59      阅读:251      评论:0      收藏:0      [点我收藏+]

标签:整数   +=   get   不为   表示   ems   auto   null   情况   

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

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

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

示例 1:

输入: dividend = $10$, divisor = $3$
输出: $3$

示例 2:

输入: dividend = $7$, divisor = $-3$
输出: $-2$

说明:

被除数和除数均为 32 位有符号整数。
除数不为 $0$。
假设我们的环境只能存储 $32$ 位有符号整数,其数值范围是 $[-2^{31}, 2^{31} - 1]$。本题中,如果除法结果溢出,则返回 $2^{31} - 1$。

 

题解:

首先, 知道除数不为零,那么溢出唯一的可能就是 $-2^{31} \div (-1) = 2^{31}$,把这个情况特判掉。再特判掉被除数为零的情况。

那么剩下来,被除数和除数都不为零,可以统一先变成两个正数相除。

由于不允许使用乘除模,首先最简单的,就是考虑累减,不过这题卡掉了累减的做法,考虑类似于快速幂那样的思路。

任何被除数 $a$,对于除数 $b$,均可以表示为  $a = (2^{k_1} + 2^{k_2} + \cdots + 2^{k_n})b + r$,其中 $r = a \bmod b$。相应的 $a / b = 2^{k_1} + 2^{k_2} + \cdots + 2^{k_n}$。

只要用左移和右移代替乘 $2$ 和除 $2$,然后找出 $k_1 \sim k_n$ 即可。

 

AC代码:

static const auto io_sync_off = []()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    return nullptr;
}();
struct Solution
{
    inline long long _abs(long long x){return x<0?-x:x;}
    int divide(int dividend, int divisor)
    {
        if(dividend==-2147483648 && divisor==-1) return 2147483647;
        if(dividend==0) return 0;
        long long f=1, a=dividend, b=divisor;
        if((a<0 && b>0) || (a>0 && b<0)) f=-1;
        a=_abs(a), b=_abs(b);

        long long res=0, t=1;
        while(a>b) b<<=1, t<<=1;
        while(a>=_abs(divisor))
        {
            while(a<b) b>>=1, t>>=1;
            a-=b, res+=t;
        }
        return f==-1?-res:res;
    }
};

 

LeetCode 29 - 两数相除 - [位运算]

标签:整数   +=   get   不为   表示   ems   auto   null   情况   

原文地址:https://www.cnblogs.com/dilthey/p/9928316.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!