题目


Given two integers dividend and divisor, divide two integers without using multiplication, division and mod operator.

Return the quotient after dividing dividend by divisor.

The integer division should truncate toward zero.

Example 1:

  Input: dividend = 10, divisor = 3

  Output: 3

Example 2:

  Input: dividend = 7, divisor = -3

  Output: -2

Note:

  • Both dividend and divisor will be 32-bit signed integers.
  • The divisor will never be 0.
  • Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: \([−2^{31}, 2^{31} − 1]\). For the purpose of this problem, assume that your function returns \(2^{31} − 1\) when the division result overflows.

思路


位移运算

(1)题意

要求我们实现两个整数的除法的操作,并且不能使用乘、除、模运算。两个整数都是32位整数,假设被除数是M,除数是m。

(2)特殊情况:溢出

除法的溢出有两种情况:

  • 除数m为0(虽然题目已经假设m不为0,但是自己还是要考虑到);
  • 被除数M是最小数INT_MIN,除数m为1。
(3)符号处理:异或

在除法操作中,同号为正,异号为负,这有点类似于异或操作:值相同异或为0,值不同异或为1。于是我们利用一个标志位来记录符号。再对被除数M和除数m取绝对值,这里注意,取绝对值时,由于32位整数范围为\([−2^{31}, 2^{31} − 1]\),在对除数m取绝对值时,必须将类型设置long或者long long型,否则当除数m为最小值时,取绝对值后会溢出。

(4)除法实现:逐渐逼近

题目要求不能利用乘、除、取模来实现除法。首先看除法的意义,假设36 / 9 = 4,将它换成36 - 9 - 9 - 9 - 9 = 0,这个时候发现可以用减法来逐渐逼近:36减去4次9等于0,而36除以9也是4(实际上减去减去4次9就是9 *4了)。另一种情况是:如果不能整除怎么办?假设36 / 8 ,它的商是4。换成36 - 8 - 8 - 8 - 8 =4 < 8,这个时候发现不够减了,就不减了,商正好是4。于是我们可以用一个循环来实现除法操作:看被除数M减去了几次除数m,将减去多次m后的值与m比较(小于等于m时),得到商。

但是,这种每次只减一个除数m的循环太慢了,程序很容易超时。我们希望每次可以多减几个m,比如2的倍数次。为什么是2的倍数次?因为两次可以用位运算实现。

m << 0 相当于m * 1

m << 1 相当于m * 2

m << 2 相当于m * 4

于是我们需要利用一个变量i来记录位运算的移动次数,以及一个临时变量来记录除数m的左移操作之后的结果(m << i)。

此时的循环变为M 与 m << i比较。

Tips


位操作(C++)

(1)位运算

|| | | |

| :---: | :---: | :---: |

| & | 逻辑与 | 0 & 1 =0 |

| | | 逻辑或 | 0 | 1 = 1 |

| ^ | 异或 | 0 ^ 1 = 1 |

| ~ | 逐位求反 | ~1 = 0 |

| << | 左移 | 8 << 1 = 16 |

| >> | 右移 | 8 >> 1 = 4 |

| <<= | 左移后赋值 | a <<=1 即 a= a<<1 |

| >>= | 右移后赋值 | a >>=1 即 a= a>>1 |

(2)用途
  • 由上面可以看出a<<b就是将a乘以2的b次方(\(a * 2^b\))。通常认为<<1要比2更快,因为位移操作是更底层的一些操作。因此程序中2的操作尽量用>>1代替,以提高程序效率。此外,可以用1<<来定义一些常量。
  • 类似地,a>>b就是将a除以2的b次方取整(\(\frac{a}{2^b}\))。通常用>>1来代替/2的操作,比如二分查找,堆的插入操作等。想办法用>>代替除法可以使程序的效率大大提高。

C++

class Solution {
public:
int divide(int dividend, int divisor) { //首先考虑特殊情况:溢出
if(divisor == 0 || (dividend == INT_MIN && divisor == -1))
return INT_MAX; //异或操作处理正负号
bool isNeg = ((dividend < 0) ^ (divisor < 0)); long m = abs((long)dividend); //被除数
long n = abs((long)divisor); //除数,这里必须是long或者long,否则取绝对值后会溢出。
long result = 0; //商
long count = 0; //记录次数 while(m >= n){ long tempVal = n; //记录左移操作的中间结果
count = 0; //每次乘以2,直到不能减为止
while(m >= (tempVal << 1)){
count ++;
tempVal <<= 1;
} m -= tempVal;
result += 1 << count;
} return isNeg ? -result : result;
}
};

Python

参考

[1] https://blog.csdn.net/a1351937368/article/details/77746574/

29. Divide Two Integers[M]两数相除的更多相关文章

  1. LeetCode OJ:Divide Two Integers(两数相除)

    Divide two integers without using multiplication, division and mod operator. If it is overflow, retu ...

  2. Divide two numbers,两数相除求商,不能用乘法,除法,取模运算

    问题描述:求商,不能用乘法,除法,取模运算. 算法思路:不能用除法,那只能用减法,但是用减法,超时.可以用位移运算,每次除数左移,相当于2倍. public class DividTwoInteger ...

  3. [LeetCode] 29. Divide Two Integers 两数相除

    Given two integers dividend and divisor, divide two integers without using multiplication, division ...

  4. [LeetCode] Divide Two Integers 两数相除

    Divide two integers without using multiplication, division and mod operator. If it is overflow, retu ...

  5. [Swift]LeetCode29. 两数相除 | Divide Two Integers

    Given two integers dividend and divisor, divide two integers without using multiplication, division ...

  6. 029 Divide Two Integers 两数相除

    不使用乘号,除号和取模符号将两数相除.如果溢出返回 MAX_INT.详见:https://leetcode.com/problems/divide-two-integers/description/ ...

  7. Java实现 LeetCode 29 两数相除

    29. 两数相除 给定两个整数,被除数 dividend 和除数 divisor.将两数相除,要求不使用乘法.除法和 mod 运算符. 返回被除数 dividend 除以除数 divisor 得到的商 ...

  8. Leetcode 29.两数相除 By Python

    给定两个整数,被除数 dividend 和除数 divisor.将两数相除,要求不使用乘法.除法和 mod 运算符. 返回被除数 dividend 除以除数 divisor 得到的商. 示例 1: 输 ...

  9. LeetCode(29): 两数相除

    Medium! 题目描述: 给定两个整数,被除数 dividend 和除数 divisor.将两数相除,要求不使用乘法.除法和 mod 运算符. 返回被除数 dividend 除以除数 divisor ...

随机推荐

  1. 九九乘法表(for循环)

    九九乘法表:<br /><script>for(var i=0;i<10;i++){ for(var j=1;j<=i;j++) { var a=j*i docum ...

  2. 【Oracle】数据迁移工具(2):Data Dump

    Data Dump 使用命令行IMPDP/EXPDP实现导入导出表.schema.表空间及数据库.IMPDP/EXPDP命令行中可以加入以下选项,来实现更细粒度的导入导出. IMPDP/EXPDP和I ...

  3. 【MySQL】ERROR 1005: Can't create table (errno: 150)的错误解决办法

    在mysql 中建立引用约束的时候会出现MySQL ERROR 1005: Can't create table (errno: 150)的错误信息结果是不能建立 引用约束. 出现问题的大致情况 1. ...

  4. (转)OpenLayers3基础教程——OL3基本概念

    http://blog.csdn.net/gisshixisheng/article/details/46756275 OpenLayers3基础教程——OL3基本概念 从本节开始,我会陆陆续续的更新 ...

  5. CorelDRAW2019版本下载,CorelDRAW最新版新增功能(全)

    使用CorelDRAW 2019,随时随地进行设计创作.无论您使用的是 Windows 或 Mac,都能在为您的平台量身设计的直观界面中,随心所欲地自由创作.无论您是热衷于像素,执迷于无缝输出或沉浸于 ...

  6. 团体程序设计天梯赛-练习集-L1-047. 装睡

    L1-047. 装睡 你永远叫不醒一个装睡的人 —— 但是通过分析一个人的呼吸频率和脉搏,你可以发现谁在装睡!医生告诉我们,正常人睡眠时的呼吸频率是每分钟15-20次,脉搏是每分钟50-70次.下面给 ...

  7. JavaScript中Null和Undefined的区别

    Null: null是js中的关键字,表示空值,null可以看作是object的一个特殊的值,如果一个object值为空,表示这个对象不是有效对象. Undefined: undefined不是js中 ...

  8. PHP第四天 函数引用传值

    <?php function f1($p1,&$p2){ $p1++; $p2++; $result= $p1+ $p2; return $result;}$v1=10;$v2=20;$ ...

  9. Windows Server 2008 R2 搭建DNS服务器(转)

    Windows Server 2008 R2 搭建DNS服务器将本机IP设为首选DNS服务器的地址在dos 下分别输入 nslookup www.mydns.com 和 nslookup 192.16 ...

  10. Cocos2d+C++运行出现中断的解决方法

    原因是引入外部的文件不存在问题,一般是路径问题,例如引入的图片文件路径不存在.