【每天学习一点算法 2026/04/13】两数相除

每天学习一点算法 2026/04/13

题目:两数相除

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

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

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

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

这道题可给我折磨坏了,其实最简单的办法就是用 dividend 一直减 divisor ,直到结果小于 divisor,减的次数就是我们要求的结果。

typescript 复制代码
function divide(dividend: number, divisor: number): number {
    let res = 0
    while (dividend >= divisor) {
      dividend -= divisor
      res++
    }
    return res
};

但是不用想肯定是超时的,这个替换一个思路其实是要在 [1, dividend] 的范围内找到一个数字 n,使他的 dividend - divisor < divisor × n <= dividend 。

这样我们就是可以利用二分查找,减少复杂度,但是求倍数又是一个问题了,官方建议用使用 快速乘 类似 Pow(x, n) 的 快速幂,像这样:

typescript 复制代码
function helper (x: number, n: number) {
  // 较小的数作为倍数
  if (x < n) {
    [x, n] = [n, x]
  }
  if (n === 1) {
    return x
  }
  if (x === 1) {
    return n
  }
  const m = n >> 1 // = Math.floor(n / 2) 利用右移代替除二
  if (m + m === n) {
      // 偶数
    return helper(x, m) + helper(x, m)
  } else {
    // 奇数
    return helper(x, m) + helper(x, m) + x
  }
}

但是遇到 dividend = 1026117192 divisor = -874002063 这种还是会超时,欺骗我感情。

最后呢,我们还是利用累加来判断 x × n 是否大于 dividend 来实现

typescript 复制代码
function divide(dividend: number, divisor: number): number {
    if (dividend === 0) return 0
    const MAX = 2147483647
    const MIN = -2147483648
    let res = 0
    let flag = (divisor > 0 && dividend > 0) || (divisor < 0 && dividend < 0) // 正负标识
    // 取绝对值做计算可以减少很多条件判断
    dividend = Math.abs(dividend) 
    divisor = Math.abs(divisor)
    if (dividend < divisor) return 0 // 除数大于被除数直接返回 0
    if (divisor === 1) {
      // 除数是 1 结果直接等于被除数
      res = dividend
    }
    if (dividend === divisor) {
      // 被除数和除数相等直接结果为1
      res = 1
    }
    
    // 辅助函数用于判断 x * n 是否大于 dividend
    function helper (x: number, n: number) {
      // 较小的数作为倍数
      if (x < n) {
        [x, n] = [n, x]
      }
      let sum = 0
      // 累加判断结果是否大于 dividend
      while (n > 0) {
        sum += x
        if (sum > dividend) {
          return false
        }
        n--
      }
      return true
    }
    
    // 二分查找目标倍数
    let left = 1, right = dividend
    while (left <= right && divisor > 1 && dividend !== divisor) {
      const mid = left + ((right - left) >> 1) // 利用右移代替除二
      const chenji = helper(divisor, mid)
      if (!chenji) {
        // divisor的mid倍大于dividend
        right = mid - 1
      } else {
        // divisor的mid倍小于等于dividend
        left = mid + 1
        res = mid
      }
    }
    // 最后根据符号返回对应结果,注意边界判断
    if (flag) {
      return Math.min(MAX, res)
    } else {
      return Math.max(MIN, -res)
    }
};

题目来源:力扣(LeetCode)

相关推荐
卿卿的产品经理日记14 分钟前
【AI产品经理实战】Day 38|try-except 踩坑实录:报错是数据
人工智能·笔记·python·学习·产品经理
keyipatience19 分钟前
TypeScript学习(1)
前端·javascript·学习·typescript·html·css3
302wanger22 分钟前
DeepSeek-V4.1-Flash-1017 免费用到1024,速来
算法
lisw0540 分钟前
微分与积分的本质区别解析
算法·数学建模·极限编程
xys_6781 小时前
深挖数据结构:树和二叉树(上)
数据结构·算法
lazy H1 小时前
【计算机网络】第 2 篇:一条数据如何穿过网络?彻底理解数据封装与解封装
网络·经验分享·后端·学习·计算机网络
我命由我123451 小时前
软件工程概念 - 可插拔性
java·后端·学习·java-ee·系统架构·软件工程·学习方法
Interview Aid1122 小时前
Google SWE Intern VO 面经:两轮 Coding,Follow-up 考察 BFS 状态
算法
琳达爱分享2 小时前
从单机令牌桶到集群限流:一次配额超发的复盘
后端·算法
range2 小时前
带TTL的LRU缓存的实现-字节手撕-26/10/19
算法