liuzhch1

LeetCode_29. 两数相除Divide Two Integers|商的二进制表示与除数的关系

Original Link: 29. Divide Two Integers

Problem description

Given two integers: dividend and divisor, return dividend/divisor without using multiplication, division, and mod operator.
The integer division should truncate toward zero, which means just discard fractional part.

Example:

Input: dividend = 10, divisor = -3
Output: -3
Explanation: 10/(-3) = -3.3333..., which should be truncated to -3.

Notes:
The dealing with an environment which could only store integers within 32-bit signed integer range: [231, 2311].
If the quotient is greater than 2311, return 2311.
If the quotient is less than 231, return 231.

Problem analysis

Firstly, we should consider the sign of divisor and dividend, in order to ignore different sign, we can turn them to same sign first. In this question, the integer bound are 32-bit signed integers, so we can only turn the divisor and dividend into negative(otherwise turn 232 to positive will overflow).

Now let's consider the division between two negative number.
We can easily come up with a naive solution: continually minus divisor to dividend till dividend become larger than divisor. In this process, we count how many divisor are subtracted.
But it's obviously inefficient, we can minus multiple divisor one time! Suppose m/n=11, 11 is 1011 in binary, which means:

m/nm1×n×240×n×231×n×221×n×21

We can find the smallest n2k such that n2k>m, then minus m with n2k, and continually minus n2k1, n2k2, ... till n<m.

Code details

class Solution {
    public int divide(int m, int n) {
        // consider special situations
        if (n == Integer.MIN_VALUE)
            return m == Integer.MIN_VALUE ? 1 : 0;
        if (m == Integer.MIN_VALUE) {
            if (n == 1)
                return m;
            if (n == -1)
                return Integer.MAX_VALUE;
        }
        if (m == 0)
            return 0;

        // turn m,n into negative
        boolean rev = false;
        if (m > 0) {
            rev = !rev;
            m = -m;
        }
        if (n > 0) {
            rev = !rev;
            n = -n;
        }

        // find the smallest n*(2^k) such that n*(2^k) > m
        int nPow = n, cnt = 0;
        // attention overflow: using - instead of nPow+nPow>=m
        while (nPow >= m - nPow) {
            nPow += nPow;
            ++cnt;
        }

        // continually minus binary pow times n
        int res = 0;
        while (m <= n) {
            if (m <= nPow) {
                res += (1 << cnt);
                m -= nPow;
            }
            nPow >>= 1;
            --cnt;
        }
        return rev ? -res : res;
    }
}

Complexity analysis

Time Complexity

O(logC), C=232

We are performing minus of binary powers times n to m( mn2k). So we can handle them in O(logm), while m is in 32-bit range. So the time complexity is O(logC), in which C is the range of 32-bit integer.

Space Complexity

O(1)

Firstly we find the smallest n2k such that n2k>m, then we perform continually minus of n2j to m if n2j>m, where j<k. And we can easily get n2j by n2j+1>>1. The total cost of space are constant, so it's O(1).


ORIGINAL POST LINK——FROM CNBLOG.liuzhch1
https://www.cnblogs.com/liuzhch1/p/leetcode29-divide-two-integers.html

posted on   liuzhch1  阅读(29)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架

导航

统计信息

点击右上角即可分享
微信分享提示