【leetcode 29】 两数相除(中等)
题目描述
给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。
返回被除数 dividend 除以除数 divisor 得到的商。
整数除法的结果应当截去(truncate)其小数部分,例如:truncate(8.345) = 8 以及 truncate(-2.7335) = -2
示例 1:
输入: dividend = 10, divisor = 3
输出: 3
解释: 10/3 = truncate(3.33333..) = truncate(3) = 3
示例 2:
输入: dividend = 7, divisor = -3
输出: -2
解释: 7/-3 = truncate(-2.33333..) = -2
解题思路
首先要考虑到数字的正负问题,如果除数和被除数都为正数或者都为负数,结果也是正数,否则为负数。使用 sign 标记正负,然后将除数和被除数都转成正数:
int sign = 1;
if ((dividend > 0 && divisor < 0) || (dividend < 0 && divisor > 0)) {
sign = -1;
}
int dividends = Math.abs(dividend);
int divisors = Math.abs(divisor);
要求不能使用乘法、除法和取余运算,算出两数相除的值,结果值取整。涉及到运算,那就得使用到别的运算符,比如加法。比如 10/3 转成 10 一直减 3,直到被减的数小于被除数。
10 - 3 = 7
7 -3 = 4
4 - 3 = 1 < 3
上面一共减了三次,所以 10/3 = 3,根据思路写出下面代码:
public int divide(int dividend, int divisor) {
int sign = 1;
if ((dividend > 0 && divisor < 0) || (dividend < 0 && divisor > 0)) {
sign = -1;
}
int dividends = Math.abs(dividend);
int divisors = Math.abs(divisor);
int index = 0;
while (dividends >= divisors) {
dividends = dividends - divisors;
index++;
}
return index * sign;
}
结果:

这里涉及到数字范围的问题,我们发现 -2147483648,取相反数还是-2147483648,这是由于编码 int 占四个字节,一个字节八个位。
所以需要使用转成 long 类型,避免数据越界问题:
int sign = 1;
if ((dividend > 0 && divisor < 0) || (dividend < 0 && divisor > 0)) {
sign = -1;
}
long dividends = Math.abs((long) dividend);
long divisors = Math.abs((long) divisor);
long index = 0;
while (dividends >= divisors) {
dividends = dividends - divisors;
index++;
}
if (index > Integer.MAX_VALUE && sign == 1) {
return Integer.MAX_VALUE * sign;
}
return (int) index * sign;
结果:

结果超时,是因为一个个减,是需要重复次数,时间复杂度是O(n)。
这里需要使用递进式的减法,比如
10/1 = 10
10 - 1 = 9 index = 1
9 - 1 = 8 index = 2
8 - 1 = 7 index = 3
7 - 1 = 6 index = 4
6 - 1 = 5 index = 5
....
1 - 1 = 0 index = 10
这上面是要进行十步操作,需要做的一个递进的操作,被除数做加倍,比如上面可以转成:
10 - 1= 9 index = 1 = 1
9 - 1*2 = 7 index = 1 + 1*2 = 3
7 - 1*2*2 = 3 index = 1 + 1*2 + 1 *2*2 = 7
再匹配 3 - 1*2*2*2 < 0,还需要再进行上面的减操作
3 - 1 = 2 index = 7 + 1 = 8
2 - 1*2 = 0 index = 7 + 1 + 1* 2 = 10
具体流程:

根据以上思路可得如下代码:
int sign = 1;
if ((dividend > 0 && divisor < 0) || (dividend < 0 && divisor > 0)) {
sign = -1;
}
long dividends = Math.abs((long) dividend);
long divisors = Math.abs((long) divisor);
long index = 0;
while (dividends >= divisors) {
long temp = divisors;
long i = 1;
while (dividends >= temp) {
dividends = dividends - temp;
index = index + i;
temp = temp << 1;
i = i << 1;
}
}
if (index > Integer.MAX_VALUE && sign == 1) {
return Integer.MAX_VALUE * sign;
}
return (int) index * sign;
总结
- 此题解法开始想到将除法转成减法,一个一个累计减
- 需要考虑 int 范围溢出问题,这里统一换成
long类型 - 累减需要的时间负复杂度是O(n),容易超时,这里需要转成递进减法,即每次都对被减数加倍
如果觉得文章对你有帮助的话,请点个推荐吧!
【leetcode 29】 两数相除(中等)的更多相关文章
- Java实现 LeetCode 29 两数相除
29. 两数相除 给定两个整数,被除数 dividend 和除数 divisor.将两数相除,要求不使用乘法.除法和 mod 运算符. 返回被除数 dividend 除以除数 divisor 得到的商 ...
- Leetcode 29.两数相除 By Python
给定两个整数,被除数 dividend 和除数 divisor.将两数相除,要求不使用乘法.除法和 mod 运算符. 返回被除数 dividend 除以除数 divisor 得到的商. 示例 1: 输 ...
- LeetCode 29 - 两数相除 - [位运算]
题目链接:https://leetcode-cn.com/problems/divide-two-integers/description/ 给定两个整数,被除数 dividend 和除数 divis ...
- leetcode 29 两数相除
问题描述 给定两个整数,被除数 dividend 和除数 divisor.将两数相除,要求不使用乘法.除法和 mod 运算符. 返回被除数 dividend 除以除数 divisor 得到的商. 示例 ...
- [LeetCode]29 两数相除和一个小坑点
给定两个整数,被除数 dividend 和除数 divisor.将两数相除,要求不使用乘法.除法和 mod 运算符. 返回被除数 dividend 除以除数 divisor 得到的商. 示例 1: 输 ...
- LeetCode 29——两数相除
1. 题目 2. 解答 2.1. 方法一 题目要求不能使用乘法.除法和除余运算,但我们可以将除法转移到对数域. \[ \frac{a}{b} = e^{\frac{lna}{lnb}} = e^{ln ...
- leetcode 29两数相除
我理解本题是考察基于加减实现除法,代码如下: class Solution { public: //只用加减号实现除法, //不用加减号实现除法: int divide(int dividend, i ...
- 【剑指 Offer II 001. 整数除法】同leedcode 29.两数相除
剑指 Offer II 001. 整数除法 解题思路 在计算的时候将负数转化为正数,对于32位整数而言,最小的正数是-2^31, 将其转化为正数是2^31,导致溢出.因此将正数转化为负数不会导致溢出. ...
- [LeetCode] 29. Divide Two Integers 两数相除
Given two integers dividend and divisor, divide two integers without using multiplication, division ...
随机推荐
- java变量的初始化之后的默认值
对于类的成员变量 不管程序有没有显示的初始化,Java 虚拟机都会先自动给它初始化为默认值. 1.整数类型(byte.short.int.long)的基本类型变量的默认值为0. 2.单精度浮点型(f ...
- Hadoop - HA学习笔记
Hadoop HA概述 工作要点 通过双NameNode消除单点故障 元数据管理方式需要改变:内存中各自保存一份元数据:Edits 日志只有 Active 状态的NameNode节点可以做写操作:两个 ...
- 针对python输入要求
针对python输入要求 类型: 1.输入行数不确定,并且每一行输入一个数据. a=[] b=input() while b!='-1': //指随意使用一个值作为一个标志,来进行控制输入的行数.(在 ...
- HTML分块
<!DOCTYPE html><html><head> <meta charset="utf-8"> <title>菜鸟 ...
- 浅谈cache
2021.9.22更新: <浅谈Cache Memory> http://blog.sina.com.cn/s/blog_6472c4cc0102dusv.html 为什么贴上这个链接呢, ...
- C++:用字符串数组实现大数运算,以两个不高于40位的大数运算为例。
因为基本数据类型中整型的内存范围有限,所以直接进行大数之间的运算,不仅浪费空间,而且运行缓慢,甚至有些会导致数据溢出. 那怎么办呢? 这时我们就想直接不行,那咱们来间接的. 这就是我们今天主要要讲的: ...
- 基于Spring Boot的线程池监控方案
前言 这篇是推动大家异步编程的思想的线程池的准备篇,要做好监控,让大家使用无后顾之忧,敬畏生产. 为什么需要对线程池进行监控 Java线程池作为最常使用到的并发工具,相信大家都不陌生,但是你真的确定使 ...
- tensorflow源码解析之common_runtime拾遗
把common_runtime中剩余的内容,按照文件名排序进行了简单的解析,时间原因写的很仓促,算是占个坑,后续有了新的理解再来补充. allocator_retry 有时候内存分配不可能一次完成,为 ...
- 如何实现ARC中weak功能?
原文链接 我们都知道ARC中weak与assign或者说unsafe_unretained最大的不同就是设置weak属性后,系统会在对象被释放后自动将指向对象的指针置为nil,而assign则会产生一 ...
- 如何修改windows Server 2012 远程桌面连接默认端口
如何修改windows Server 2012 远程桌面连接默认端口 修改windows 2012/win8.win7远程桌面连接默认端口一般需要修改注册表四个地方[HKEY_LOCAL_MACH ...