Part1 函数
二.两数相除
题目链接:<29. 两数相除 - 力扣(LeetCode)>
知识模块:
INT_MAX=231-1;INT_MIN=-231。
思路:
- 分析特殊值:dividend=0/divisor=1/diviser=-1(注意取反可能会溢出)
- 引入符号,把a(dividend),b(divisor)全变成 负数(防溢出) 方便计算
- 引入一个参量count,设其初值为1,引入一个tb,赋值为b(为了后续计算不改变b值)
- 以2n的速度迅速逼近结果
例:202304/24
(24)+(24)<=(202304)
count=2, tb=48
原式=2+(202304-48)/24
(48)+(48)<=(202304)
count=4, tb=96
原式=4+(202304-96)/24
……
原式=8429+(202304-202296)/24
202304-202296=8<24 跳出循环
算法:
- 用if语句计算特殊值
- 定义符号sign,同号取1异号取-1
- 判断a,b是否为负,不是就变成负
- 表达式:a/b=count+(a-b*count)/b
- 令tb初值为b,循环:count自加,b自加,a减去之后返回新值
- 若a>b,退出循环(a,b为负数)
代码:
class Solution {
public:
int divide(int dividend, int divisor) {
if (dividend == 0) return 0;
if (divisor == 1) return dividend;
if (divisor == -1) {
return dividend == INT_MIN ? INT_MAX : -dividend;//若为最小整数INT_MIN,取反为2^31超过最大整数,此时取最大整数INT_MAX
}
int a = dividend;
int b = divisor;
int sign = 1;
if ((a > 0 && b < 0) || (a < 0 && b>0)) {
sign = -1;
}
a = a > 0 ? -a : a;
b = b > 0 ? -b : b;//a,b全部转为负数防止溢出
int res = div(a, b);
return sign == -1 ? -res : res;
}//根据原a,b的正负判断结果的正负
int div(int a, int b) {
if (a > b) return 0;//|a|<|b|,即不能再除得整数
int count = 1;
int tb = b;//把b的值赋给一个临时的tb上,后续不改变b值
while (tb >= a - tb) {
count += count;
tb += tb; //
}//按照思路4设计,可迅速逼近所求值
return count + div(a - tb, b);//返回解的值,交给上方符号判断
}
};
注意:
- 第25行循环条件不可以写成((tb+tb)>=a),这样也会造成超出数值边界 即溢出!
- 若环境无存储空间限制,可转为正数计算,更符合思维,此时把int换成long扩大空间即可防止溢出。