LeetCode剑指offer第一遍刷题_第一题

272 阅读4分钟

10月11日

第一题

剑指 Offer II 001. 整数除法

题目

  • 给定两个整数 ab ,求它们的除法的商 a/b ,要求不得使用乘号 '*'、除号 '/' 以及求余符号 '%'
  • 整数除法的结果应当截去(truncate)其小数部分,例如:truncate(8.345) = 8 以及 truncate(-2.7335) = -2
  • 假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231, 231−1]。本题中,如果除法结果溢出,则返回 231 − 1

知识点:

^异或运算符
true(1)异或任何数 其结果=任何数取反
false(0)异或任何书 其结果=任何数
越界问题
//32位 最大值: 2^31-1 = 2147483647
//32位 最小值: -2^31 = -2147483648
如果说a的值为负的最小值,b的值为-1将会越界
-2147483647 / -1  = 2147483648 > 2147483647 就会越界

//位移运算符,说先需要有原码,补码,反码的知识
注意:位移运算符是会补符号位,而不是固定补0 如果你的符号位为1,那么就会补1
1.左位移运算符 <<
    例如 5 的二进制写法为 101
    使用左移运算符后
    5<<1 = 1010 
    也就是 数字10 的二进制写法
    因为你左移动一位,左移运算符会在后面补0所以就变成了10
    (你可以把他理解为乘2,但是如果说要进行位移的值是一个小数,那么会先向下取整为整数后再去位移)
2.右位移运算符 >>
    例如 5 的二进制写法为 101
	使用右位移运算符后
    5>>1 = 010
	也就是 数字2 的二进制写法
    因为你向右移动一位,有运算符会删除最后一位然后在前面补0
    (你可以理解为除2(向下取整),但是如果说要进行位移的值是一个小数,那么会先向下取整,然后在进行位移)
3.无符号右移运算符 >>>
    例如 -5 的二进制写法为 -101
	使用无符号右移运算符后
    -5>>>1 = -11
	也就是 数字-3 的二进制写法
    (具体这里我没有太看明白,但是我也是给他理解为除二然后向下取整,希望有大佬能在评论补充一下感谢!)
var divide = function(a, b) {
 //先声明出来一个最大值和最小值
 const INT_MIN = -Math.pow(2, 31)
 const INT_MAX = Math.pow(2, 31) - 1
	//判断a是否等于最大值且b等于-1 为了防止越界
 if (a == INT_MIN && b == -1){
     //如果是的话直接返回最大值
     return INT_MAX
 } 
	//判断我们的值是正数还是负数
 const sign = (a > 0) ^ (b > 0) ? -1 : 1
 //获取到a和b的绝对值
 //如果a或者b是最小值的话,那么你取的绝对值还是最小值
 a = Math.abs(a)
 b = Math.abs(b)
	//声明一个变量用来记录次数
 let res = 0
	//为什么要循环31次?因为最大值和最小值都是31次方
 for (let x = 31; x >= 0; x--) {
     	//采用右移的原因是 右移永远不会越界
		//因为a要右移x位 如果 a为最小值,那么使用右移运算符就会变成一个负数
     	//所以要使用无符号右移运算符,将其变成一个稳定的正数
     	//他和右移的值是一样的,但是右移是负数,而无符号右移是正数
		//这里为什么要 - b ? 因为你一个值右移多少值去减去最小值那么永远都是小于0的
     	//所以他就会一直返回false 就比如 1-(-2147483647)
     	//我在控制台去 console.log(1-(-2147483647)) 他的结果是 2147483648
     	//但是在cmd中返回的就是负的最小值,是因为在 32 位中 2147483648 是越界了的
     	//所以会返回最小值 -2147483647
     if ((a >>> x) - b >= 0) {
         //如果结果为true就去计算 a-(b<<x)位
         //但是这行我实际上还不是很明白
         a = a - (b << x)
         //res这里是用来计算当前的商是多少的
         res = res + (1 << x)
     }
 }
 if (res == -2147483648) return -2147483648
 // bug 修复:因为不能使用乘号,所以将乘号换成三目运算符
 return sign == 1 ? res : -res
};

总结

今天是第一遍刷题第一天,感觉蛮吃力其实,算法的基础很差,今天学会了异或运算符左移/右移运算符,至于无符号运算符我目前的理解还处于在他只会补0 前面两个是会补符号位。

如果注释有什么错误,希望各位大佬在评论区指出,我去改正,非常感谢!