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: \([-2^{31},\ 2^{31}-1]\).
If the quotient is greater than \(2^{31}-1\), return \(2^{31}-1\).
If the quotient is less than \(-2^{31}\), return \(-2^{31}\).
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 \(-2^{32}\) 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:
We can find the smallest \(n\cdot2^k\) such that \(n\cdot2^k>m\), then minus \(m\) with \(n\cdot2^k\), and continually minus \(n\cdot2^{k-1},\ n\cdot2^{k-2},\ ...\) 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(\log C),\ C=2^{32} \]We are performing minus of binary powers times \(n\) to \(m\)( \(m-n\cdot2^k\)). So we can handle them in \(O(\log m)\), while \(m\) is in 32-bit range. So the time complexity is \(O(\log C)\), in which \(C\) is the range of 32-bit integer.
Space Complexity
\[O(1) \]Firstly we find the smallest \(n\cdot2^k\) such that \(n\cdot2^k>m\), then we perform continually minus of \(n\cdot2^j\) to \(m\) if \(n\cdot2^j>m\), where \(j<k\). And we can easily get \(n\cdot2^j\) by \(n\cdot2^{j+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