当前位置: 首页 > news >正文

位运算题目:两数相除

文章目录

  • 题目
    • 标题和出处
    • 难度
    • 题目描述
      • 要求
      • 示例
      • 数据范围
  • 解法
    • 思路和算法
    • 代码
    • 复杂度分析

题目

标题和出处

标题:两数相除

出处:29. 两数相除

难度

6 级

题目描述

要求

给定两个整数,被除数 dividend \texttt{dividend} dividend 和除数 divisor \texttt{divisor} divisor,要求不使用乘法、除法和取余运算符,计算两个整数的除法。

整数除法的结果应当向零取整,即去掉分数部分。例如, 8.345 \texttt{8.345} 8.345 取整得到 8 \texttt{8} 8 -2.7335 \texttt{-2.7335} -2.7335 取整得到 -2 \texttt{-2} -2

注意:假设我们的环境只能存储 32 \texttt{32} 32 位有符号整数,其数值范围是 [−2 31 , 2 31 − 1] \texttt{[−2}^\texttt{31}\texttt{, 2}^\texttt{31} − \texttt{1]} [231, 2311]。对于这道题,如果商严格大于 2 31 − 1 \texttt{2}^\texttt{31} - 1 2311 则返回 2 31 − 1 \texttt{2}^\texttt{31} - 1 2311,如果商严格小于 -2 31 \texttt{-2}^\texttt{31} -231 则返回 -2 31 \texttt{-2}^\texttt{31} -231

示例

示例 1:

输入: dividend = 10, divisor = 3 \texttt{dividend = 10, divisor = 3} dividend = 10, divisor = 3
输出: 3 \texttt{3} 3
解释: 10/3 = 3.33333.. \texttt{10/3} = \texttt{3.33333..} 10/3=3.33333..,取整得到 3 \texttt{3} 3

示例 2:

输入: dividend = 7, divisor = -3 \texttt{dividend = 7, divisor = -3} dividend = 7, divisor = -3
输出: -2 \texttt{-2} -2
解释: 7/-3 = -2.33333.. \texttt{7/-3} = \texttt{-2.33333..} 7/-3=-2.33333..,取整得到 -2 \texttt{-2} -2

数据范围

  • -2 31 ≤ dividend, divisor ≤ 2 31 − 1 \texttt{-2}^\texttt{31} \le \texttt{dividend, divisor} \le \texttt{2}^\texttt{31} - \texttt{1} -231dividend, divisor2311
  • divisor ≠ 0 \texttt{divisor} \ne \texttt{0} divisor=0

解法

思路和算法

由于题目要求给定的环境只能存储 32 32 32 位有符号整数,因此不考虑使用 long \texttt{long} long 型的解法。虽然使用 long \texttt{long} long 型可以简化实现,但是不符合题目要求。

由于被除数 dividend \textit{dividend} dividend 的最大值是 2 31 − 1 2^{31} - 1 2311,最小值是 − 2 31 -2^{31} 231,因此商不在 32 32 32 位有符号整数范围中的情况只有 dividend = − 2 31 \textit{dividend} = -2^{31} dividend=231 divisor = − 1 \textit{divisor} = -1 divisor=1 的情况,此时商是 2 31 2^{31} 231,超出 32 32 32 位有符号整数范围,应返回 2 31 − 1 2^{31} - 1 2311

以下三种情况可以直接返回结果,优先处理。

  • 如果 dividend = 0 \textit{dividend} = 0 dividend=0,则商是 0 0 0,返回 0 0 0

  • 如果 divisor = 1 \textit{divisor} = 1 divisor=1,则商与被除数相等,返回 dividend \textit{dividend} dividend

  • 如果 dividend = − 2 31 \textit{dividend} = -2^{31} dividend=231 divisor = − 1 \textit{divisor} = -1 divisor=1,则商是 2 31 2^{31} 231,超出 32 32 32 位有符号整数范围,因此返回 2 31 − 1 2^{31} - 1 2311

其余情况,为了方便处理,首先根据被除数和除数的正负性判断商的正负性,然后将被除数和除数都变成负数,计算商的绝对值。将被除数和除数都变成负数是为了可以处理 − 2 31 -2^{31} 231 的情况。

由于题目要求不能使用乘法和除法,因此需要使用移位运算代替乘法和除法。

首先将除数左移,使得在除数的绝对值不超过被除数的绝对值的情况下,将除数的绝对值最大化。假设除数左移了 k k k 位之后变成 currDivisor \textit{currDivisor} currDivisor,则 currDivisor = divisor × 2 k \textit{currDivisor} = \textit{divisor} \times 2^k currDivisor=divisor×2k currDivisor \textit{currDivisor} currDivisor 除以 divisor \textit{divisor} divisor 的商是 2 k 2^k 2k。因此将结果增加 2 k 2^k 2k,将 dividend \textit{dividend} dividend 的值减去 currDivisor \textit{currDivisor} currDivisor,然后对剩余的 dividend \textit{dividend} dividend 继续计算商。

dividend \textit{dividend} dividend 的值减去 currDivisor \textit{currDivisor} currDivisor 之后,如果 dividend \textit{dividend} dividend 的绝对值小于 currDivisor \textit{currDivisor} currDivisor 的绝对值,则需要将 currDivisor \textit{currDivisor} currDivisor 右移,直到 dividend \textit{dividend} dividend 的绝对值大于等于 currDivisor \textit{currDivisor} currDivisor 的绝对值,然后重复上述操作,计算两数相除的结果。当 dividend \textit{dividend} dividend 的绝对值小于 divisor \textit{divisor} divisor 的绝对值时,商的剩余部分取整的结果是零,因此结束计算,此时即可得到两数相除的结果的绝对值,根据事先判断的商的正负性得到两数相除的结果。

需要注意的是,由于上述计算过程比较的是绝对值,而 dividend \textit{dividend} dividend divisor \textit{divisor} divisor currDivisor \textit{currDivisor} currDivisor 都是负数,因此比较两数之间关系的不等号方向与比较两数绝对值之间关系的不等号方向相反。

以下用一个例子说明计算过程。被除数 dividend \textit{dividend} dividend − 512 -512 512,除数 divisor \textit{divisor} divisor − 5 -5 5。用 quotient \textit{quotient} quotient 表示两数相除的结果的绝对值,用 factor \textit{factor} factor 表示将 divisor \textit{divisor} divisor 左移之后对应的因数,初始时 quotient = 0 \textit{quotient} = 0 quotient=0 factor = 1 \textit{factor} = 1 factor=1

  1. divisor \textit{divisor} divisor 左移 6 6 6 位,得到 currDivisor = factor × 2 6 = − 5 × 64 = − 320 \textit{currDivisor} = \textit{factor} \times 2^6 = -5 \times 64 = -320 currDivisor=factor×26=5×64=320 factor = 2 6 = 64 \textit{factor} = 2^6 = 64 factor=26=64。此时 currDivisor \textit{currDivisor} currDivisor 是将 factor \textit{factor} factor 左移之后的不小于 dividend \textit{dividend} dividend 的最小值(对应绝对值最大)。

  2. quotient \textit{quotient} quotient 的值增加 factor \textit{factor} factor,将 dividend \textit{dividend} dividend 的值减少 currDivisor \textit{currDivisor} currDivisor。此时 quotient = 64 \textit{quotient} = 64 quotient=64 dividend = − 192 \textit{dividend} = -192 dividend=192

  3. 由于 dividend > currDivisor \textit{dividend} > \textit{currDivisor} dividend>currDivisor,因此将 currDivisor \textit{currDivisor} currDivisor 右移 1 1 1 位,使得 dividend ≤ currDivisor \textit{dividend} \le \textit{currDivisor} dividendcurrDivisor,此时 currDivisor = − 160 \textit{currDivisor} = -160 currDivisor=160 factor = 32 \textit{factor} = 32 factor=32。将 quotient \textit{quotient} quotient 的值增加 factor \textit{factor} factor,将 dividend \textit{dividend} dividend 的值减少 currDivisor \textit{currDivisor} currDivisor。此时 quotient = 96 \textit{quotient} = 96 quotient=96 dividend = − 32 \textit{dividend} = -32 dividend=32

  4. 由于 dividend > currDivisor \textit{dividend} > \textit{currDivisor} dividend>currDivisor,因此将 currDivisor \textit{currDivisor} currDivisor 右移 3 3 3 位,使得 dividend ≤ currDivisor \textit{dividend} \le \textit{currDivisor} dividendcurrDivisor,此时 currDivisor = − 20 \textit{currDivisor} = -20 currDivisor=20 factor = 4 \textit{factor} = 4 factor=4。将 quotient \textit{quotient} quotient 的值增加 factor \textit{factor} factor,将 dividend \textit{dividend} dividend 的值减少 currDivisor \textit{currDivisor} currDivisor。此时 quotient = 100 \textit{quotient} = 100 quotient=100 dividend = − 12 \textit{dividend} = -12 dividend=12

  5. 由于 dividend > currDivisor \textit{dividend} > \textit{currDivisor} dividend>currDivisor,因此将 currDivisor \textit{currDivisor} currDivisor 右移 1 1 1 位,使得 dividend ≤ currDivisor \textit{dividend} \le \textit{currDivisor} dividendcurrDivisor,此时 currDivisor = − 10 \textit{currDivisor} = -10 currDivisor=10 factor = 2 \textit{factor} = 2 factor=2。将 quotient \textit{quotient} quotient 的值增加 factor \textit{factor} factor,将 dividend \textit{dividend} dividend 的值减少 currDivisor \textit{currDivisor} currDivisor。此时 quotient = 102 \textit{quotient} = 102 quotient=102 dividend = − 2 \textit{dividend} = -2 dividend=2

  6. 此时 dividend > divisor \textit{dividend} > \textit{divisor} dividend>divisor,即 dividend \textit{dividend} dividend 的绝对值小于 divisor \textit{divisor} divisor 的绝对值,结束计算。由于初始时 dividend \textit{dividend} dividend divisor \textit{divisor} divisor 的符号相同,因此结果是正数,返回 quotient = 102 \textit{quotient} = 102 quotient=102

代码

class Solution {public int divide(int dividend, int divisor) {if (dividend == 0) {return 0;}if (divisor == 1) {return dividend;}if (dividend == Integer.MIN_VALUE && divisor == -1) {return Integer.MAX_VALUE;}boolean negative = dividend < 0 ^ divisor < 0;dividend = -Math.abs(dividend);divisor = -Math.abs(divisor);int quotient = 0;int currDivisor = divisor, factor = 1;while (dividend >> 1 < currDivisor) {currDivisor <<= 1;factor <<= 1;}while (dividend <= divisor) {while (dividend > currDivisor) {currDivisor >>= 1;factor >>= 1;}quotient += factor;dividend -= currDivisor;}if (negative) {quotient = -quotient;}return quotient;}
}

复杂度分析

  • 时间复杂度: O ( log ⁡ ∣ dividend ∣ ) O(\log |\textit{dividend}|) O(logdividend),其中 dividend \textit{dividend} dividend 是给定的被除数。计算 currDivisor \textit{currDivisor} currDivisor 的过程中,左移操作的次数是 O ( log ⁡ ∣ dividend ∣ ) O(\log |\textit{dividend}|) O(logdividend) 次,计算商的过程中需要将 currDivisor \textit{currDivisor} currDivisor 右移,每次右移之后最多更新结果一次,因此时间复杂度是 O ( log ⁡ ∣ dividend ∣ ) O(\log |\textit{dividend}|) O(logdividend)

  • 空间复杂度: O ( 1 ) O(1) O(1)

相关文章:

  • 测试基础笔记第十五天
  • AI日报 - 2025年04月29日
  • esm使用-包括esmfold和embedding
  • 阿里开源图生动画模型AnimateAnyone2
  • auto(x) decay copy
  • await和async
  • 2025年保安员证考试题库及答案
  • 【quantity】4 Duration 类型及其实现(time.rs)
  • C22-作业练习之最大公约数与最小公倍数
  • 如何开发动态贴纸功能?一体化美颜SDK的技术实现思路与实战方案
  • ZYNQ-自定义呼吸灯IP核以及PS-PL数据发送接收
  • Easy系列PLC高速计数器比较指令
  • 跟着文档学Vuex(一):什么是Vuex
  • 小智项目架构分析
  • uniapp实现统一添加后端请求Header方法
  • 如何评价 DeepSeek 的 DeepSeek-V3 模型?
  • OpenAvatarChat要解决UnicodeDecodeError
  • 云服务器主动防御策略与自动化防护(下)
  • MySQL最新版9.3.0安装教程
  • 【C++游戏引擎开发】第28篇:OpenGL异步加载纹理技术详解
  • 国家发改委回应美加征关税:典型的单边主义霸凌做法
  • 梅花画与咏梅诗
  • 玉渊谭天丨“稀土管制让美国慌了”,美军工稀土储备仅够数月
  • 航天科技集团质量技术部部长严泽想升任集团副总经理
  • 破解160年基因谜题,我国科学家补上豌豆遗传研究最后拼图
  • 朝中社发表评论文章,谴责美军部署B1-B轰炸机至日本