Leetcode29 Divide Two Integers

Leetcode29 Divide Two Integers

题意理解

题目全文如下:
Given two integers dividend and divisor, divide two integers without using multiplication, division and mod operator.

Return the quotient after dividing dividend by divisor.

The integer division should truncate toward zero.

Example 1:

Input: dividend = 10, divisor = 3
Output: 3

Example 2:

Input: dividend = 7, divisor = -3
Output: -2

Note:

  • Both dividend and divisor will be 32-bit signed integers.
    The divisor will never be 0.
  • Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [−231, 231 − 1]. For the purpose of this problem, assume that your function returns 231 − 1 when the division result overflows.

题目大致的意思是不用乘法,除法和取余实现整数除法.如果除法涉及的整数过大,则报溢出的异常.

解题思路

首先,题目说了不能用乘法和除法以及取余,那么我们可以用的只有加法,减法和位运算.乘法可以用加法来实现,于是很自然的可以想到除法用减法来实现.例如9除以3,可以用一个循环减法来实现,每次加一,直到被减数小于3为止.

想到这个之后,基本上问题解决了一半,接下来考虑优化的问题.本题中最大的数是-2^31,也就是2 147 483 648,这个数大于10的8次方,如果这个数除以1,那么算法运行时间就会超时.首先从一个例子入手,

21 ÷ 3 = 7 21\div3=7 21÷3=7
21 ÷ 6 = 3 , 21 m o d 6 = 3 , 3 ÷ 3 = 1 21\div6=3,21mod6=3,3\div3=1 21÷6=3,21mod6=3,3÷3=1
6 ÷ 3 = 2 , 7 = 2 × 3 + 1 6\div3=2,7=2\times3+1 6÷3=2,7=2×3+1
21除以3等于7,21除以6等于3余数为3,3除以3等于1.2乘以3加一为7.
到这里我们可以发现规律,除以一个数的值等于除以这个数的N倍得到的商乘以N加上这个数的余数除以这个数得到的结果.于是优化思路就显而易见了.

位运算可以用来代替乘法,所以我们可以左移除数,直到找到刚好小于被除数的第一个数,然后减去它,同时将1左移相同的位数得到一个结果,将这个结果加到最终的商中,递归运行这个过程,直到被除数小于除数为止,输出返回最后的结果,在这个过程中注意处理溢出.代码如下所示:

代码

#include <iostream>

using namespace std;

class Solution {
public:
    int divide(int dividend, int divisor) {
        # define MAX_INT 2147483648
        bool positive = ((dividend >=0 && divisor > 0) || (dividend < 0 && divisor < 0))? 1 : 0;
        unsigned int count = 1;
        unsigned int unsigndividend = dividend;
        if(dividend == INT_MIN){
            unsigndividend = MAX_INT;
        }
        else{
            unsigndividend = abs(dividend);
        }
        unsigned int undivisor = divisor;
        if(divisor == INT_MIN){
            undivisor = MAX_INT;
        }
        else{
            undivisor = abs(divisor);
        }
        unsigned int res=0;
        for(int i=31;i>=0;i--){
            if(unsigndividend>>i >= undivisor){
                unsigndividend-=undivisor<<i;
                res+=count<<i;
            }
        }
        if(positive && res >= MAX_INT){
            res = MAX_INT-1;
        }
        else{
            res=positive?res:-res;
        }
        return res;
    }
};

int main() {
    Solution se;
    cout<<se.divide(-2147483648, -1)<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值