29. 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, which means losing its fractional part. For example, truncate(8.345) = 8 and truncate(-2.7335) = -2.
Example 1:
Input: dividend = 10, divisor = 3
Output: 3
Explanation: 10/3 = truncate(3.33333…) = 3.
Example 2:
Input: dividend = 7, divisor = -3
Output: -2
Explanation: 7/-3 = truncate(-2.33333…) = -2.
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/divide-two-integers
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
Think and method
Before describing the method, we need to consider a few special cases.
Let’s say the dividend is m and the divisor is n
1, N = 0, result = 0
2、m = -2^31 n = -1
result = 2 ^ 31 out of bound, thus return 2 ^ 31 -1
Method 1. Optimization of subtraction
Considering this problem, topic request we don’t use the multiplication, division and mod to achieve division, first of all, we can think of is to use the learning division at the time of the train of thought, using the subtraction, the dividend is minus the divisor, and eventually be able to get the correct results, but in actual implementation, this method is very inefficient, beyond the topic the required time limit, as a result, we need some optimization.
Shorten the calculation time, dichotomy!
The process of using shift to realize dichotomy also conforms to the requirement of not using multiplication, division and MOD, which is concise and clear.
Time complexity: O(logn)
Space complexity: O(n)
Method 2 addition and shift
In fact, in general algorithmic thinking, method two is not fundamentally different from method two, but method two makes use of the idea of recursion.
Let’s say I take 27/4 for example
1、
4 * 2 * 2 =16 < 27 < 4 * 2 * 2 * 2 = 32
we get 4 in this step
2、27-16 = 11
4 * 2 =8< 11 < 4 * 2 * 2=16
we get 2 in this step
3、11-8 = 3
3 < 4
ignore it
The result is: 4+2=6
We can see that the second and third steps do exactly the same thing, simplifying it with just one recursive procedure.
Time complexity: O(n)
Space complexity: O(n)
Codes:
1、
func divide(dividend int, divisor int) int {
//special situatiom when divisor = 0
if divisor == 0 {
return 0
}
// consider overflow -2^31/-1 = 2^31 > 2^31 -1
if divisor == -1 && dividend == -(math.MaxInt32+1) {
return math.MaxInt32
}
//get the abs of numbers
dividend_abs := int(math.Abs(float64(dividend)))
divisor_abs := int(math.Abs(float64(divisor)))
result := calculate(dividend_abs, divisor_abs)
//nagative number add symbol
if (dividend >= 0 && divisor < 0) || (dividend <= 0 && divisor > 0){
return -result
}
return result
}
func calculate(dividend int, divisor int) int{
result := 0
if divisor == 1 {
result = dividend
dividend = 0
}
guess, compare := 31, 0
for compare+divisor <= dividend {
if compare+divisor<<guess <= dividend {
//Dichotomous comparison
compare += divisor << guess
result += 1 << guess
}
guess--
}
return result
}
2、
func divide(dividend int, divisor int) int {
//special situatiom when divisor = 0
if divisor == 0 {
return 0
}
// consider overflow -2^31/-1 = 2^31 > 2^31 -1
if divisor == -1 && dividend == -(math.MaxInt32+1) {
return math.MaxInt32
}
//get the abs of numbers
dividend_abs := int(math.Abs(float64(dividend)))
divisor_abs := int(math.Abs(float64(divisor)))
result := calculate(dividend_abs, divisor_abs)
//nagative number add symbol
if (dividend >= 0 && divisor < 0) || (dividend <= 0 && divisor > 0){
return -result
}
return result
}
func calculate(dividend int, divisor int) int {
result := 0
for dividend >= divisor {
multi := 1
for multi * divisor <= (dividend >> 1) {
multi <<= 1
}
result += multi
// next circulation
dividend -= multi*divisor
}
return result
}
Test:
Example 1:
Input: dividend = 10, divisor = 3
Example 2:
Input: dividend = 7, divisor = -3
Special example:
Input: dividend = 7, divisor = 0
From the point of view of efficiency, dichotomy is the better method