题目描述 给定两个整数 dividend - 被除数和 divisor - 除数,在不使用乘法、除法和取余的前提下求两个数的商,商要靠 0 取整。其中:-2^31 < dividend, divisor < 2^31 - 1,且 divisor != 0。
示例:
输入: dividend = 10, divisor = 3 输出: result = 3
输入: dividend = 7, divisor = -3 输出: -2
思路 不使用乘法、除法和取余,那就只能使用加减法了。商的本质就是看被除数中包含多少倍的除数,所以最终只要看多少个除数加起来的和小于且最接近被除数,这个个数就是最终的答案。
思路一 这是我最开始的思路,不停的从 dividend 中减去 divisor 并累加次数,直到 dividend < divisor,此时的累计次数就是结果。不过这种方式效率太低,会超时。
思路二 在思路一的基础上进行改进,改用累加和与 dividend 比较。思路一中每次只增加一倍的 divisor,当被除数很大的时候,操作次数也会非常多。那能不能每次多处理一些呢?比如第一次 1 * divisor,累加 1,第二次 2 * divisor,累加 2,直到 tempSum + n * divisor > dividend,即被除数小于 n 倍的除数的时候,再将被除数与 n 倍的除数之间的差拿出来,按照思路一的方式去算。答案是肯定的,使用这种方式可以通过。
思路三 思路二中每次只增加一倍的 divisor,效率还是有点低,比如当 dividend=100_000_00,divisor=3的时候,依次算 3 + 6 + 9 + 12 + 15 + … + (n * 3) <? dividend,是比思路一要开一些,但是也是非常的慢。那试试引入幂增呢?每一次不是增加一倍的 divisor,而是将当前的累加和直接翻倍,再比较和 dividend 的大小,这时上面的运算变成:3, 6, 12, 24, 48, 96, 192…,速度比思路二要快得多。这种思路叫做“快速乘”。
代码实现 思路二中的累加方式(类快速乘思路,可通过):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 func divide2 (dividend int , divisor int ) int { if divisor == 0 { panic ("Bad parameter" ) } sign := 1 if dividend >= 0 && divisor < 0 || dividend <= 0 && divisor > 0 { sign = -1 } d1 := int (math.Abs(float64 (dividend))) d2 := int (math.Abs(float64 (divisor))) sum := 0 times := 1 result := 0 for (sum + times*d2) <= d1 { sum += times * d2 result += times times++ } if sum < d1 { for sum+d2 <= d1 { sum += d2 result++ } } result = sign * result if result > math.MaxInt32 { return math.MaxInt32 } else if result < math.MinInt32 { return math.MinInt32 } else { return result } }
思路三快速乘:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 func divide3 (dividend int , divisor int ) int { if divisor == 0 { panic ("Bad parameter" ) } sign := 1 if dividend >= 0 && divisor < 0 || dividend <= 0 && divisor > 0 { sign = -1 } d1 := int (math.Abs(float64 (dividend))) d2 := int (math.Abs(float64 (divisor))) result := 0 for d2 <= d1 { tempSum := d2 multiple := 1 for 2 * tempSum <= d1 { tempSum *= 2 multiple *= 2 } d1 -= tempSum result += multiple } result *= sign if result > math.MaxInt32 { return math.MaxInt32 } else if result < math.MinInt32 { return math.MinInt32 } else { return result } }