开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 10 天,点击查看活动详情
引言
算法的技能对于程序员是百益而无一害,作为程序员无论是前端还是后端算法技能对于我们都是十分十分的重要,我将陆续整理并讲解前端程序员必须掌握的经典算法。
题目描述
给你两个整数,被除数 dividend 和除数 divisor。将两数相除,要求 不使用 乘法、除法和取余运算。
整数除法应该向零截断,也就是截去(truncate)其小数部分。例如,8.345 将被截断为 8 ,-2.7335 将被截断至 -2 。
返回被除数 dividend 除以除数 divisor 得到的 商 。
注意: 假设我们的环境只能存储 32 位 有符号整数,其数值范围是 [−231, 231 − 1] 。本题中,如果商 严格大于 231 − 1 ,则返回 231 − 1 ;如果商 严格小于 -231 ,则返回 -231 。
示例 1:
输入: dividend = 10, divisor = 3
输出: 3
解释: 10/3 = 3.33333.. ,向零截断后得到 3 。
示例 2:
输入: dividend = 7, divisor = -3
输出: -2
解释: 7/-3 = -2.33333.. ,向零截断后得到 -2 。
提示:
-231 <= dividend, divisor <= 231 - 1divisor != 0
分析
**思路: :根据「前言」部分的讨论,记被除数为 XXX,除数为 YYY,并且 XXX 和 YYY 都是负数。需要找出 X/YX/YX/Y 的结果 ZZZ,ZZZ 一定是正数或 000。
根据除法以及余数的定义,可以将其改成乘法的等价形式,即:
Z×Y≥X>(Z+1)×Y Z \times Y \geq X > (Z+1) \times Y Z×Y≥X>(Z+1)×Y 因此,可以使用二分查找的方法得到 ZZZ,即找出最大的 ZZZ 使得 Z×Y≥XZ \times Y \geq XZ×Y≥X 成立。
由于不能使用乘法运算符,因此需要使用「快速乘」算法得到 Z×YZ \times YZ×Y 的值。「快速乘」算法与「快速幂」类似,前者通过加法实现乘法,后者通过乘法实现幂运算。「快速幂」算法可以参考「50. Pow(x, n)」的官方题解,「快速乘」算法只需要在「快速幂」算法的基础上,将乘法运算改成加法运算即可。
解答
class Solution { public int divide(int dividend, int divisor) { // 考虑被除数为最小值的情况 if (dividend == Integer.MIN_VALUE) { if (divisor == 1) { return Integer.MIN_VALUE; } if (divisor == -1) { return Integer.MAX_VALUE; } } // 考虑除数为最小值的情况 if (divisor == Integer.MIN_VALUE) { return dividend == Integer.MIN_VALUE ? 1 : 0; } // 考虑被除数为 0 的情况 if (dividend == 0) { return 0; } // 一般情况,使用类二分查找 // 将所有的正数取相反数,这样就只需要考虑一种情况 boolean turn = false; if (dividend > 0) { dividend = -dividend; turn = !turn; } if (divisor > 0) { divisor = -divisor; turn = !turn; } int left = 1, right = Integer.MAX_VALUE, ans = 0; while (left <= right) { // 注意溢出,并且不能使用除法 int mid = left + ((right - left) >> 1); boolean check = quickAdd(dividend, divisor, mid); if (check) { ans = mid; // 注意溢出 if (mid == Integer.MAX_VALUE) { break; } left = mid + 1; } else { right = mid - 1; } } return turn ? -ans : ans; } public boolean quickAdd(int x, int y, int z) { // x 和 y 是负数,z 是正数 // 需要判断 z * y >= x 是否成立 int result = 0, add = y; while (z != 0) { if ((z & 1) != 0) { // 需要保证 result + add >= x if (result < x - add) { return false; } result += add; } if (z != 1) { // 需要保证 add + add >= x if (add < x - add) { return false; } add += add; } // 不能使用除法 z >>= 1; } return true; } }
总结
上面的算法思路让我学到了许多知识啊,希望大家继续努力,继续加油啊,加油。哈哈哈哈。