leetcode 29 两数相除
问题描述
给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。
返回被除数 dividend 除以除数 divisor 得到的商。
示例 1:
输入: dividend = 10, divisor = 3
输出: 3
示例 2:
输入: dividend = 7, divisor = -3
输出: -2
说明:
- 被除数和除数均为 32 位有符号整数。
- 除数不为 0。
- 假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231, 231 − 1]。本题中,如果除法结果溢出,则返回 231 − 1。
这个问题涉及到了计算机如何利用逻辑运算和加减法来求得除法,这个问题之前一度困扰了我很久。
/**
* 逼近
* 先定符号
* 结果是正是负还是0?
* @param dividend
* @param divisor
* @return
*/
public static int divide(int dividend, int divisor) {
if (dividend == 0) {
return 0;
}
if (dividend == Integer.MIN_VALUE && divisor == -1) {
return Integer.MAX_VALUE;
}
if (divisor == -1) {
return -dividend;
}
if (divisor == 1) {
return dividend;
}
int res = 0, Sum = 0;
boolean plus = false;
//同号
if ((dividend > 0 && divisor > 0) || (dividend < 0 && divisor < 0)) {
plus = true;
}
//将两个数都变成负数
dividend = dividend > 0 ? ~dividend + 1 : dividend;
divisor = divisor > 0 ? ~divisor + 1 : divisor;
for (int i = 30; i > -1; i--) {
//被加数未溢出 加之后的结果未溢出 加之后的结果小于被除数
int addNum = divisor<<i;
if (addNum>>i == divisor && Sum + addNum < 0 && Sum + addNum >= dividend) {
Sum += addNum;
res += plus ? 1<<i : -1<<i;
}
}return res;
}
题解(写代码时候的奇怪想法。。。):
首先进行边界处理之类的。
一开始我采用了二分法猜数字,首先做一个记号记录结果,然后把被除数(dividend)和除数(divisor)都转换为正数 (信息加工),这样结果就一定是在[0,dividend]。
初始化left = 0, right = dividend,mid = dividend << 1;
然后通过for循环累加mid次验证是否符合结果( mid * divisor <= dividend并无法取到比mid更大的mid'去满足前面条件);
由于平时并不是经常使用二分碰到了以下问题:
二分的边界问题:
如何写出不杂乱的代码?
因为常常使用 mid = (left + right)<<1;
故而遗忘了mid还可以向右偏 mid = ((left + right)<<1) + 1;。
因为要保证结果一定在边界内,故而
left = mid + 1; right = mid - 1;常常不能同时出现(视情况而定吧)。
所以有时候
采用 right = mid - 1; left = mid;这个组合时:
mid = (left + right)<<1; (left + 1 = right) 时候回卡死!
这个时候要mid = ((left + right)<<1) + 1;(向右偏)
当然这样的思路写出来的代码的结果就是我挂了。。
for循环累加代替乘法实在太慢了!!!
然鹅,这时候我想到了一个办法。
divisor * mid 可以写成 divisor (m0 * 2^31 + m1 * 2^30 + m2 * 2^31 ....+m30 * 2^0)
然后二的m次方这个东西我是可以通过左移来得到的!
于是我兴奋地用这个方法验证mid对不对。
发现很多边界问题无法解决
例如:
之前说的右偏碰到Integer.MIN_VALUE
Integer.MIN_VALUE无法转换为正数
mid取得太大,数据溢出,本来divisor * mid已经超过了Integer.MAX_VALUE。却还是几千。。。
于是我处于崩溃的边缘。。。
这样搞下去我要屎了!
然鹅,解手的时候。我想:
我可以把所有数都转换为负数先啊
我可以不用猜测mid是多少啊
我直接从一步一步逼近被除数就行啦??? 好像真的是。。
例如 :
结果如若为101010111...(32位)
那么我从头开始的非符号位开始看能不能加进去就好啦! 如若能加进去就逼近了被除数,数据本身溢出,加进去溢出,加进去大于被除数就代表不能加!
其他的都加,反正我要的也是最逼近的数。。。
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 得到的商. 示例 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 ...
- LeetCode(29): 两数相除
Medium! 题目描述: 给定两个整数,被除数 dividend 和除数 divisor.将两数相除,要求不使用乘法.除法和 mod 运算符. 返回被除数 dividend 除以除数 divisor ...
随机推荐
- POJ 2455:Secret Milking Machine(二分+最大流)
http://poj.org/problem?id=2455 题意:给出n个点和m条无向路,每条路都有一个长度.从1点到n点要走t次两两互不重合的路.求出每条1->n的路中相邻两点最大值的最小值 ...
- iOS自动化探索(十)代码覆盖率统计
iOS APP代码覆盖率统计 今年Q3季度领导给加了个任务要做前后端代码覆盖率统计, 鉴于对iOS代码代码比较熟就选择先从iOS端入手,折腾一整天后终于初步把流程跑通了记录如下 覆盖率监测的原理 Xc ...
- 【POJ - 1979 】Red and Black(dfs+染色)
-->Red and Black Descriptions: 有个铺满方形瓷砖的矩形房间,每块瓷砖的颜色非红即黑.某人在一块砖上,他可以移动到相邻的四块砖上.但他只能走黑砖,不能走红砖. 敲个程 ...
- ZigBee按键查询实践
按键查询 即硬件上电后,程序开始运行,当检测到按键按下,触发按键语句,执行按键触发的事件: 玩单片机需要清楚两件东西,第一个是单片机的电路图,另一个则是单片机的寄存器: CC2530是51的升级版,我 ...
- kuangbin专题 专题一 简单搜索 Shuffle'm Up POJ - 3087
题意:(1)有两副颜色多样的扑克牌,(A~H)表示不同颜色,给你两副牌,S1,S2和一副你需要洗出的KEY,S12由S2最底部,S1底部...一直下去,直到洗成S12,就是图片展示的那样.(2)洗好的 ...
- 成功解决 org.mybatis.spring.MyBatisSystemException问题!!
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.binding.BindingExce ...
- Appium+python自动化(二十)- 猴哥失散多年的混血弟弟还是妹妹- Monkey(猴子)日志(超详解)
简介 日志是非常重要的,用于记录系统.软件操作事件的记录文件或文件集合,可分为事件日志和消息日志.具有处理历史数据.诊断问题的追踪以及理解系统.软件的活动等重要作用,在开发或者测试软系统过程中出现了问 ...
- HashMap源码分析(二):看完彻底了解HashMap
上文讲到HashMap的增加方法,现在继续 上文链接 HashMap在上一篇源码分析的文章中,如果使用put的时候如果元素数量超过threshold就会调用resize进行扩容 1.扩容机制 想要了解 ...
- PCB SQL SERVER 数据库阻塞进程关系以思维导图方式呈现的实现方法
最近公司服务数据库同步机制常发生阻塞,时不时的导致PCB工程系统卡死现象,只有找到阻塞源头并处理掉,才以消除阻塞,但数据库中查看会话阻塞是通过二维表方式展示的父子会话进程ID的,是很难清楚的展示各会话 ...
- JAVA AES文件加解密
AES加解密算法,代码如下: /** * Created by hua on 2017/6/30. */ import javax.crypto.Cipher; import javax.crypto ...