Leetcode 0029.Divide Two Integers(python)
29. Divide Two Integers
你选用何种方法解题?
本题的核心是不使用乘法、除法和取模运算实现整数除法。
| 方法 | 时间复杂度 | 空间复杂度 | 是否推荐 |
|---|---|---|---|
| 位运算(位移法) | O(log n) | O(1) | 推荐 |
| 负数倍增法 | O(log n) | O(1) | 推荐 |
方法选择理由:
- 位运算(位移法):通过左移实现快速乘法,时间效率高
- 负数倍增法:使用负数处理避免溢出问题,更安全
解题过程
问题分析
输入:被除数 dividend,除数 divisor
输出:两数相除的商(截断小数部分)
关键约束:
- 不能使用乘法、除法、取模运算
- 需要处理溢出情况
核心洞察
- 位运算替代乘法:
x << k等价于x * 2^k - 二分查找思想:找到最大的
k使得divisor * 2^k <= dividend - 符号处理:先记录符号,将问题转化为正数或负数除法
- 负数处理:使用负数避免
abs(INT_MIN)溢出
算法流程(负数倍增法)
以 dividend = 15, divisor = 3 为例:
1 | 符号:正 |
这些方法具体怎么运用?
方法一:位运算(位移法)
核心逻辑:
- 处理边界情况:溢出、除数为1、除数为-1
- 记录符号:
sign = -1 if (dividend < 0) ^ (divisor < 0) else 1 - 转化为正数:使用绝对值
- 位运算加速:
- 从高位到低位遍历(31位)
- 如果
divisor << i <= dividend,则商加上1 << i,并减去相应值
- 返回结果:应用符号并处理溢出
方法二:负数倍增法(推荐)
核心逻辑:
- 处理边界情况:唯一溢出情况
dividend = INT_MIN, divisor = -1 - 记录符号:
negative = (dividend > 0) != (divisor > 0) - 转化为负数:全部转为负数避免
abs(INT_MIN)溢出 - 倍增查找:
- 内层循环:找到最大的
value = divisor * 2^k - 外层循环:减去当前最大倍数,累加商
- 内层循环:找到最大的
- 返回结果:应用符号
边界情况处理:
| 边界情况 | 处理方式 |
|---|---|
dividend = INT_MIN, divisor = -1 |
返回 INT_MAX(溢出) |
divisor = 1 |
直接返回 dividend |
divisor = -1 |
返回 -dividend(注意溢出) |
dividend = 0 |
返回 0 |
复杂度
| 方法 | 时间复杂度 | 空间复杂度 | 说明 |
|---|---|---|---|
| 位运算(位移法) | O(log n) | O(1) | n 是被除数的绝对值 |
总结与最佳选择
最快算法:两种方法时间复杂度相同。
工程最优选择:负数倍增法。理由如下:
- 避免溢出:使用负数处理,避免
abs(INT_MIN)溢出问题 - 代码简洁:逻辑清晰,易于理解
- 安全性高:不需要额外的溢出检查
各方法适用场景:
- 负数倍增法:生产环境首选,避免溢出问题
- 位运算(位移法):代码直观,适合教学
Code
方法一:位运算(位移法)
1 | class Solution: |
方法二:负数倍增法(推荐)
1 | class Solution: |
All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.

