题目
给定两个整数 a 和 b ,求它们的除法的商 a/b ,要求不得使用乘号 ‘*’、除号 ‘/’ 以及求余符号 ‘%’ 。
注意:
整数除法的结果应当截去(truncate)其小数部分,例如:truncate(8.345) = 8 以及 truncate(-2.7335) = -2
假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−2^31, 2的31次方−1]。本题中,如果除法结果溢出,则返回 2的31次方 − 1
代码带注释
#include <iostream>
#include <limits.h>
using namespace std;
class Solution {
public:
/* 将a和b都化成正整数,但-2147483648的绝对值还是-2147483648 因为在数字在计算机中存储都是以补码的形式
* 那么就不会满足循环条件,就立马退出
* 如果换成负整数,则不会发生此问题
* 空间复杂度o(1),时间复杂度o(n) 因为如果a=-2147483648 b=1; k = 2147483648 = n
*/
int divide(int a, int b)
{
int sign = (a > 0)^(b > 0) ? -1 : 1;
// 一、考虑越界问题
// 32位最大值:2^31-1 = 2147483647
// 32位最小值:-2^31 = -2147483648
// 如果a = -2147483648 b = -1 那么结果是 2147483648 越界
if(a == INT_MIN && b == -1)
{
return INT_MAX;
}
//二、考虑题目要求
//因为题目要求只支持32位
// a = abs(a);
// b = abs(b);
if(a>0)a = -a;
if(b>0)b = -b;
int res = 0;
while(a <= b)
{
a -= b;
res++;
}
// 不能用乘号,所以将乘号换成三目运算符
return sign == 1 ? res : -res;
}
/*
* 空间复杂度o(1),时间复杂度:O(logn * logn),n 是最大值 2147483647 --> 10^10
*/
int divide_1(int a, int b)
{
if(a == INT_MIN && b == -1)
{
return INT_MAX;
}
int sign = (a > 0)^(b > 0) ? -1 : 1;
if(a>0)a = -a;
if(b>0)b = -b;
cout<<"a:"<<a<<" b:"<<b<<endl;
int res = 0;
while(a <= b)
{
int value = b;
int k = 1;
// 0xc0000000 是十进制 -2^30 的十六进制的表示
// 判断 value >= 0xc0000000 的原因:保证 value + value 不会溢出
// 可以这样判断的原因是:0xc0000000 是最小值 -2^31 的一半,
// 而 a 的值不可能比 -2^31 还要小,所以 value 不可能比 0xc0000000 小
// -2^31 / 2 = -2^30
while(value >= 0xc0000000 && a <= value + value){
value += value;
//如果k = 最大值的一半的话,INT_MAX/2 = 1,073,741,823.5 那么直接返回最小值
//因为这个时候k+k肯定会大于 2147483648 这个超过了题目给出的范围
if(k>1073741823){
return INT_MIN;
}
k += k;
}
a -= value;
res += k;
}
cout<<"rojek"<<endl;
return sign == 1 ? res : -res;
}
};
int main()
{
system("chcp 65001");
Solution a1;
int result = a1.divide_1(-2147483648,1);
cout<<"result: "<<result<<endl;
// cout<<pow(2,31)-1<<endl;
return 0;
}
注意问题
1.由于题目限制了数字的使用范围,如果将负数全部化为整数处理 那么会出现
这样问题 对int的最小值-2^31取绝对值 会等于该数 ,因为在计算机中存储的数字都是以补码的形式来存储的限定了int32位范围 那么就会产生溢出,如果换成long的话 那么久不会符合题目的要求
2.整数的补码就是其本身,负数的补码等于反码+1
具体可以参考一下链接:
1.https://www.jianshu.com/p/5d899b71266d?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation
2.https://blog.csdn.net/qq_44715943/article/details/115418965?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-2-115418965-blog-7429197.pc_relevant_multi_platform_featuressortv2dupreplace&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-2-115418965-blog-7429197.pc_relevant_multi_platform_featuressortv2dupreplace&utm_relevant_index=5
3.在线程序计算器
http://cal.apple886.com/
做题步骤
1.先把基本(能实现大部分样例的)的代码写出来
2.再注意边界问题
3.再回过来仔细阅读题目的要求
做到不紧不慢,有条理