剑指 Offer II 001. 整数除法



解题思路

  • 在计算的时候将负数转化为正数,对于32位整数而言,最小的正数是-2^31, 将其转化为正数是2^31,导致溢出。因此将正数转化为负数不会导致溢出。
  • 设置一个变量,用来记录正数个数,以便在最后的结果调整正负号。
  • 特殊情况,可能溢出的情况讨论,由于是整数除法,除数不为0,商的值一定小于等于被除数的绝对值,因此,int型溢出只有一种情况,(-2^31)/(-1) = 2^31。

最容易想到的是通过减法代替除法,但是会超时

class Solution {
public int divide(int a, int b) {
if(a == 0)return 0;
int symbolNum = (a>0)^(b>0)? -1:1 ;//可以对下面的代码段进行优化
/*
int symbolNum = 1;
if(a>0&&b>0 || a<0&&b<0) symbolNum = 1;
else{
symbolNum = -1;
}*/ if(a==Integer.MIN_VALUE && b==-1) return Integer.MAX_VALUE; if(a>0)a = -a;
if(b>0)b = -b;
int ans = 0;
while(a <= b){
a -= b;
ans++;
}
return symbolNum == -1? -ans:ans;
}
}

优化思路

不使用减法那种被除数对除数一次一次减的形式(在被除数过大而除数很小的情况下会超时),而是试图减2个、4个、8个....找到最大的2的n次方。将被除数减去除数的2的n次方倍,然后将剩余的被除数重复前面的步骤。

例如:

为了求得15/2的商,先从15里减去8 (23),得到7;再从7里减去4(22),得到3;再从3里减去2(2^1),得到1,此时1小于2,因此商是3+2+1=7。

在计算两个负数的除法时,防止每次计算除数的2倍,会导致大数溢出,要保证计算2倍之后的数大于(-231)/2。如果时计算两个正数的除法,要保证计算2倍之后的数小于(231-1)/2。

class Solution {
public int divide(int a, int b) {
//int 型整数的除法只有一种情况会导致溢出,即(-2^31)/(-1)
if(a==Integer.MIN_VALUE && b==-1) return Integer.MAX_VALUE;
if(a == 0 || b == 1)return a;
else if(b == -1) return -a;
int symbolNum = (a>0)^(b>0)? -1:1 ;
// 由于(-2^31) 转换为正数会溢出,但是任意正数转换为负数都不会溢出
// 故,记录负数的个数,并将正数转换为负数方便统一计算
if(a>0)a = -a;
if(b>0)b = -b; // while(a <= b){//这样写确实可以过案例,但是会超时
// a -= b;
// ans++;
// }
if(a == b)return symbolNum == -1? -1:1;
int ans = 0;
while(a<=b){//小于是因为现在a,b都是负数
int value = b;//统计最多有几个减数(2的n次方个)
int tmpQuotient = 1;
while(value + value > Integer.MIN_VALUE && value + value >= a){//减到不够了为止
value += value;
tmpQuotient += tmpQuotient;
}
ans +=tmpQuotient;
a -= value;
} return symbolNum == -1? -ans:ans;
} }

但上述代码只通过了700+样例,找了半天发现是value + value > Integer.MIN_VALUE这里出问题了,要改成value >0xc0000000。(0xc0000000是Integer.MIN_VALUE的一半)

完整代码贴在这儿

class Solution {
public int divide(int a, int b) {
//int 型整数的除法只有一种情况会导致溢出,即(-2^31)/(-1)
if(a==Integer.MIN_VALUE && b==-1) return Integer.MAX_VALUE;
if(a == 0 || b == 1)return a;
else if(b == -1) return -a;
int symbolNum = (a>0)^(b>0)? -1:1 ;
// 由于(-2^31) 转换为正数会溢出,但是任意正数转换为负数都不会溢出
// 故,记录负数的个数,并将正数转换为负数方便统一计算
if(a>0)a = -a;
if(b>0)b = -b; // while(a <= b){//这样写确实可以过案例,但是会超时
// a -= b;
// ans++;
// }
if(a == b)return symbolNum == -1? -1:1;
int ans = 0;
while(a<=b){//小于是因为现在a,b都是负数
int value = b;//统计最多有几个减数(2的n次方个)
int tmpQuotient = 1;
while(value >0xc0000000 && value + value >= a){//减到不够了为止
value += value;
tmpQuotient += tmpQuotient;
}
ans +=tmpQuotient;
a -= value;
} return symbolNum == -1? -ans:ans;
} }

这里补充一下int 类型数据的最大值,最小值及其十六进制表示方式:

在int类型(32位)中:

正整数的最大值为 0x7fffffff 也就是十进制的 2147483647

正整数的最小值为 0x00000001 也就是十进制的 1

0表示为:0x00000000

负整数的最大值为 0xffffffff 也就是十进制的 -1

负整数的最小值为 0x80000000 也就是十进制的 -2147483648

【剑指 Offer II 001. 整数除法】同leedcode 29.两数相除的更多相关文章

  1. 刷题-力扣-剑指 Offer II 055. 二叉搜索树迭代器

    剑指 Offer II 055. 二叉搜索树迭代器 题目链接 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/kTOapQ 著作权归领扣网络所有 ...

  2. 剑指Offer - 九度1504 - 把数组排成最小的数

    剑指Offer - 九度1504 - 把数组排成最小的数2014-02-06 00:19 题目描述: 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.例如输 ...

  3. 剑指Offer - 九度1352 - 和为S的两个数字

    剑指Offer - 九度1352 - 和为S的两个数字2014-02-05 18:15 题目描述: 输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于 ...

  4. 【剑指Offer】孩子们的游戏(圆圈中最后剩下的数) 解题报告(Python)

    [剑指Offer]孩子们的游戏(圆圈中最后剩下的数) 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-in ...

  5. 【剑指Offer面试编程题】题目1505:两个链表的第一个公共结点--九度OJ

    题目描述: 输入两个链表,找出它们的第一个公共结点. 输入: 输入可能包含多个测试样例. 对于每个测试案例,输入的第一行为两个整数m和n(1<=m,n<=1000):代表将要输入的两个链表 ...

  6. 【剑指Offer面试编程题】题目1214:丑数--九度OJ

    把只包含因子2.3和5的数称作丑数(Ugly Number).例如6.8都是丑数,但14不是,因为它包含因子7. 习惯上我们把1当做是第一个丑数.求按从小到大的顺序的第N个丑数. 输入: 输入包括一个 ...

  7. 剑指Offer 数值的整数次方

    题目描述 给定一个double类型的浮点数base和int类型的整数exponent.求base的exponent次方.   思路: 要考虑边界,0,负数   AC代码: class Solution ...

  8. 剑指offer之关于整数的处理

    首先是整数次方的处理 在这处理的时候有几个细节主义处理 1.当指数是负数的时候 2.当指数式0的时候 3.当不满足条件的时候要抛出异常 再一个就是常用的将一个树化为二进制的形式,或者是求整数的幂或者矩 ...

  9. 《剑指offer》-统计整数二进制表示中1的个数

    题目描述 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. 直观思路就是把二进制表示从右往左统计1的个数.直接想到移位操作来迭代处理.坑点在于负数的移位操作会填充1.有人贴出了逻辑移位 ...

随机推荐

  1. gin框架使用Air实时加载

    Air实时加载 本章我们要介绍一个神器--Air能够实时监听项目的代码文件,在代码发生变更之后自动重新编译并执行,大大提高gin框架项目的开发效率. 1.1.1. 为什么需要实时加载? 之前使用Pyt ...

  2. gin框架中的路由拆分与注册

    基本的路由注册 下面最基础的gin路由注册方式,适用于路由条目比较少的简单项目或者项目demo. package main import ( "net/http" "gi ...

  3. golang中的并发安全和锁

    1. 并发安全 package main import ( "fmt" "sync" ) var ( sum int wg sync.WaitGroup ) f ...

  4. golang中int、float、string数据类型之间的转换

    package main import ( "fmt" "strconv" ) func main() { var num1 int = 88 var num2 ...

  5. golang中数组指针和指针数组当做函数参数如何修改数组中的值

    先理解:数组指针它的类型时指针,指针数组它的类型时数组 1. 数组指针当做函数的参数 package main import "fmt" func changeData(dataA ...

  6. 返回void-(响应ajax,响应json格式)(了解)

    将jquery库文件加入到idea中 引入json依赖 index.jsp中 设置按钮发起ajax请求 从处理器方法返回void,响应ajax请求 MyController中

  7. 通俗易懂详解iptables

    防火墙相关概念 从逻辑上讲.防火墙可以大体分为主机防火墙和网络防火墙. 主机防火墙:针对于单个主机进行防护. 网络防火墙:往往处于网络入口或边缘,针对于网络入口进行防护,服务于防火墙背后的本地局域网. ...

  8. python网络爬虫-解析网页(六)

    解析网页 主要使用到3种方法提取网页中的数据,分别是正则表达式.beautifulsoup和lxml. 使用正则表达式解析网页 正则表达式是对字符串操作的逻辑公式 .代替任意字符 . *匹配前0个或多 ...

  9. %r和%s的区别

    理解%r和%s的区别 %r会重现所表达的对象,%s会将所有转成字符串 eg1: print('i am %s years old' % 22) print('i am %r years old' % ...

  10. 学习MyBatis必知必会(5)~了解myBatis的作用域和生命周期并抽取工具类MyBatisUtil、mybatis执行增删改查操作

    一.了解myBatis的作用域和生命周期[错误的使用会导致非常严重的并发问题] (1)SqlSessionFactoryBuilder [ 作用:仅仅是用来创建SqlSessionFactory,作用 ...