LeetCode 第29题:两数相除

LeetCode 第29题:两数相除

题目描述

给你两个整数,被除数 dividend 和除数 divisor。将两数相除,要求 不使用 乘法、除法和取余运算。

整数除法应该向零截断,也就是截去(truncate)其小数部分。例如,8.345 将被截断为 8 ,-2.7335 将被截断为 -2 。

返回被除数 dividend 除以除数 divisor 得到的 商 。

注意:假设我们的环境只能存储 32 位 有符号整数,其数值范围是 [−2^31, 2^31 − 1] 。本题中,如果商 严格大于 2^31 − 1 ,则返回 2^31 − 1 ;如果商 严格小于 −2^31 ,则返回 −2^31 。

难度

中等

题目链接

点击在LeetCode中查看题目

示例

示例 1:

输入:dividend = 10, divisor = 3
输出:3
解释:10/3 = 3.33333... ,向零截断后得到 3

示例 2:

输入:dividend = 7, divisor = -3
输出:-2
解释:7/-3 = -2.33333... ,向零截断后得到 -2

提示

  • -2^31 <= dividend, divisor <= 2^31 - 1
  • divisor != 0

解题思路

方法:优化的位运算

使用位运算和减法来实现除法,通过将除法转换为减法并使用位移来优化性能。

关键点:

  1. 全程使用负数处理,避免溢出
  2. 使用位移优化减法过程
  3. 处理特殊情况(最小值、溢出等)
  4. 优化符号处理逻辑

具体步骤:

  1. 处理特殊情况:
    • 处理除数为±1的情况
    • 处理最小值除以-1的溢出
  2. 将问题转化为负数处理:
    • 记录结果符号
    • 转换为负数避免溢出
  3. 使用位移和减法计算商:
    • 找到最大的移位次数
    • 累加商的结果
  4. 根据符号返回最终结果

时间复杂度:O(log n)
空间复杂度:O(1)

图解思路

位运算过程示意图

步骤 被除数 除数 移位次数 当前商 剩余值
1 -10 -3 1 2 -4
2 -4 -3 0 1 -1
3 -1 -3 0 0 -1

优化策略分析

情况 处理方式 原因 示例
除数为1 直接返回被除数 无需计算 10/1=10
除数为-1 需要处理溢出 最小值变正数会溢出 -2^31/(-1)
普通情况 转为负数处理 避免溢出 7/(-3)=-2

代码实现

public class Solution {
    public int Divide(int dividend, int divisor) {
        // 处理特殊情况
        if (dividend == int.MinValue && divisor == -1) {
            return int.MaxValue;
        }
        if (divisor == 1) {
            return dividend;
        }
        if (divisor == -1) {
            return -dividend;
        }
      
        // 记录符号并转换为负数处理(避免溢出)
        bool isNegative = (dividend > 0) ^ (divisor > 0);
        int a = dividend > 0 ? -dividend : dividend;
        int b = divisor > 0 ? -divisor : divisor;
      
        // 计算结果
        int result = 0;
        while (a <= b) {
            int temp = b;
            int multiple = -1;
          
            // 找到最大的移位次数
            while (temp >= (int.MinValue >> 1) && a <= (temp << 1)) {
                temp <<= 1;
                multiple <<= 1;
            }
          
            a -= temp;
            result += multiple;
        }
      
        // 处理符号
        return isNegative ? result : -result;
    }
}

执行结果

  • 执行用时:24 ms
  • 内存消耗:26.4 MB

代码亮点

  1. 🎯 巧妙使用负数处理避免溢出
  2. 💡 高效的位运算优化
  3. 🔍 完善的特殊情况处理
  4. 🎨 清晰的代码结构和命名

常见错误分析

  1. 🚫 没有处理溢出情况
  2. 🚫 使用正数处理导致溢出
  3. 🚫 位运算边界判断错误
  4. 🚫 符号处理逻辑错误

解法对比

解法 时间复杂度 空间复杂度 优点 缺点
减法模拟 O(n) O(1) 实现简单 效率低
二分查找 O(log n) O(1) 性能适中 实现复杂
优化位运算 O(log n) O(1) 性能最佳 需要处理边界

相关题目

posted @   旧厂街小江  阅读(0)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示